=== Divi Autopilot ===
Contributors: abcreative
Tags: divi, ai, claude, mcp, accessibility, seo, audit
Requires at least: 6.4
Tested up to: 7.1
Requires PHP: 8.0
Stable tag: 1.8.2
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Connect Claude to Divi 5. Build and edit Divi-native pages by conversation, then audit what ships — and fix it.

== Description ==

Divi Autopilot is a remote MCP server for Divi 5 by Abcreative, LLC. Add the connector URL to Claude and it can read your site's design system, build and restructure Divi-native pages, and audit the whole site — accessibility, SEO, performance, legal furniture, site QA and design consistency — with one-click fixes, an undo journal, and a single Autopilot Site Score that shows its own arithmetic.

* 86 MCP tools (43 free) — pages, design system, Theme Builder, WooCommerce, Loop Builder, dynamic content, media, snapshots
* 6 audit suites that state what they cannot see — content generated at render is declared unreadable, never guessed at
* Per-finding waivers only the site owner can grant; the agent deliberately has no tool for them
* Scheduled audits that email only when something changed; client report export
* Reads and adopts the design system your site already has, then builds to it
* A 1,700+ check self-test against the live install
* Admin UI in nine languages (EN, FR, DE, ES, IT, PT-BR, NL, PL, JA)

Free tier: all free tools, site-wide read-only audits, and fixes on one bound page. Pro: fixes everywhere, fix a cause across every page at once, scheduled audits, client reports, the full design-system toolset.

Audit output is informational only — not a certification of ADA/WCAG or legal compliance, and not legal advice.

Divi is a registered trademark of Elegant Themes, Inc. Divi Autopilot is an independent product, not affiliated with, authorized by, endorsed by, or sponsored by Elegant Themes, Inc.

== Installation ==

1. Upload and activate the plugin.
2. Open Divi Autopilot → Overview and copy the connector URL (your key is inside it — treat it like a password).
3. In claude.ai or the Claude desktop app: Settings → Connectors → Add custom connector → paste the URL.
4. Ask Claude to audit or build a page. Diagnostics → Self-test proves the connection if anything refuses.

Safety posture: staging first, writes off until you are ready, independent backups on. The plugin's revisions, snapshots and one-step undo are conveniences, not backups.

== Frequently Asked Questions ==

= Does it change my live site? =
Only when writes are enabled and you ask it to. Every write preserves the prior content; owner safety switches (read-only, draft-only, protect design) can only be tightened from a conversation — loosening them is wp-admin only.

= Is a clean audit a compliance guarantee? =
No. Audits are automated static analysis: a floor, not a certification. Each suite states its blind spots in its own output.

= Which languages? =
The admin UI ships in nine languages and follows your WordPress site language. Audit findings are English in this release.

== Changelog ==

= 1.8.2 =
* THEME BUILDER TEMPLATES NOW ACTUALLY ASSIGN. divi_create_theme_template accepted the documented short conditions ("singular:post") and stored them verbatim; Divi kept them happily and resolved none of them — the template sat "Unassigned" in the Theme Builder UI and never matched on the front end. Conditions are now translated to the setting ids Divi resolves (singular:post becomes singular:post_type:post:all), real ids pass through verbatim, and an id this install cannot resolve is refused with the real list instead of stored as a dud.
* OMITTED SLOTS INHERIT THE GLOBAL CHROME. A body-only template used to store "no layout" for header and footer, so Divi answered with the THEME's stock header on every page the template matched — silently replacing the site chrome. Empty slots now inherit the default template's layouts (the Theme Builder UI's "Use Global Header"), and deleting a template with its layouts can no longer trash a layout another template still references — which, with inheritance, could have been the site's global header.
* Loop Builder fields (loop_post_title, loop_post_link and friends) are now recognized as dynamic content by the token audit. The pattern the Loop Builder requires — a $variable embedded in markup — warned "Token id does not exist and will resolve to nothing" while resolving perfectly. Found building this plugin's own blog index.
* Nine new self-test checks pin all three: condition round-trips are asserted in Divi's vocabulary against the live settings options, an omitted slot must read back the global layout, a deleted template must leave shared layouts standing, and loop fields must pass the token audit.
* The fixture reclaim from 1.8.1 now covers design tokens too. An aborted self-test run leaked its 'unique' test color; because every leaked copy carries the same fixture value, the next run's tokenize check saw an AMBIGUOUS literal and the whole group false-failed permanently. Token, preset and probe-page fixtures are now reclaimed on entry — found on this plugin's own marketing site, three leaked colors deep.

= 1.8.1 =
* GUTENBERG AND CLASSIC CONTENT ARE NOW READ BY THE AUDITS. The content collector only understood Divi modules: core blocks keep their markup in innerHTML, which was never scanned, and classic-editor content was skipped outright. A Gutenberg post therefore measured zero headings and zero internal links — and the SEO audit told the owner it "links to no other page on the site" about posts full of links. Found dogfooding this plugin's own blog on the day it launched.
* The collector now runs non-Divi block innerHTML and freeform chunks through the same HTML scanner the Divi text modules use, so headings, links, images, iframes and inputs in posts count everywhere downstream: the SEO internal-link check, the accessibility heading, alt and link-text checks, and the client report.
* Five new self-test checks pin it: a core/heading counts as a heading, a core/paragraph anchor is harvested with its href and classifies as internal through the exact counter the audit uses, and classic content is scanned rather than skipped.
* The self-test now reclaims pattern fixtures a killed or concurrent run left behind, so leaked QA debris can no longer fail every later run with "a pattern with id dvc-qa-copied already exists" — found the same evening, on our own second site.

= 1.8.0 =
* THE LAST TWO ITEMS FROM THE CUSTOMER PANEL, SHIPPED. The panel's top all-panels frustration — "I fixed a finding and the tab badge still said ×5" — and its Agency ask, white-label reports, were the two open rows on its build list. Both close here.
* A LANDED FIX RE-CHECKS ITS PAGE. Every fix door — single fix, review applies (alt, CTA, contrast), Fix All, and undo — now re-audits the touched page inside the stored run: findings swapped, counts corrected, waivers re-anchored, and the rail badge updated from the response. The fix message says what the re-check found instead of sending you to re-run a forty-page audit. Fix All re-checks inside a time budget and says plainly when the remainder waits for the next run; score HISTORY still only records at finished audits, so the series stays a record of measurements.
* WHITE-LABEL CLIENT REPORTS, on every paid plan — the plans differ by seats, and that stays true. Settings → Client reports takes your business name and a logo from the Media Library; the report header and footer then carry your brand and drop ours. The logo is embedded into the report file itself, so the document keeps its no-external-requests promise offline and in email. The engine version stays in an HTML comment for support, and the Divi trademark notice stays because the content still names Divi.
* Eleven new self-test checks pin both features, including that a re-audit never writes score history and that a white-labelled report drops the product attribution without dropping the trademark notice.

= 1.7.3 =
* LICENCE SEATS ARE NOW RELEASED ON UNINSTALL — the oldest documented open bug is closed. WordPress runs a plugin's uninstall.php INSTEAD of any registered uninstall hook, so shipping that file silently stopped Freemius ever being told the plugin was removed: delete the plugin, reinstall on another site, and a single-site licence was already spent. Freemius' deployment checker refuses zips carrying the file for exactly this reason.
* The full cleanup sweep (credentials first, multisite-aware, audit table, report files) moved from uninstall.php into DVC_Uninstall, registered on Freemius' after_uninstall action — so the SDK releases the seat, then the sweep runs. When the SDK is absent, a register_uninstall_hook fallback keeps the sweep; the multisite walk now also clears prefixed transients per subsite, which the old file only cleared on the main site.
* The packager now refuses any build containing uninstall.php, and the self-test pins that the file stays deleted, that both registration paths exist, and that the sweep only runs during a real uninstall.

= 1.7.2 =
* SECOND DOGFOOD FIND, SAME CLIENT SITE: the plugin's own test fixtures were being audited as the customer's content. Four Guardian probe pages stranded by runs the 1.7.1 lock bug killed were titled outside every swept prefix — so the SEO audit reported "only 3 words of readable text" and Site QA reported a broken attribute path, on pages the customer never made. Both audits went clean the moment the debris was removed.
* The probes are retitled under the swept 'dvc qa ' prefix, the old name is legacy-swept so pages leaked by earlier versions are reclaimed on the next run, and the fixture closure now documents why every title it takes must stay under the prefix (it is invisible to the sweep-coverage scan).
* Two new self-test checks pin the prefix and the legacy sweep.

= 1.7.1 =
* FOUND DOGFOODING ON WP ENGINE, FIXED SAME DAY. On hosts with a persistent object cache (WP Engine, and any memcached/Redis drop-in), a chunked self-test could pin itself at the same cursor forever: the run lock was a transient with a TTL, which on such hosts lives ONLY in the cache — never the database — so routine cache eviction erased the lock mid-pause, and the resume path reaped the paused run as abandoned. Every continue call restarted, re-ran the same twenty seconds, and was reaped again.
* The lock is now a DB-backed option with its own expiry stamp, and every read and write of the lock AND the paused-state option flushes the object-cache key — the host's cache can neither evict the run nor serve it stale.
* This is the cross-request half of a lesson the code had already learned in-request (0.61.1, same host): shared state you cannot afford to lose belongs in the database, read back from the database.
* Uninstall sweeps the lock in both its lives; three new self-test checks pin the DB backing, the cache-busting, and the cleanup.

= 1.7.0 =
* THE CONNECTION PILL. Every screen of the app now says, at a glance, when the site last heard from Claude: green while requests are fresh, quiet while recent, amber after a silent week, grey when no client has ever called in. The pill links to the Connection tab.
* HONEST BY DESIGN: a stateless HTTP connector holds no socket open, so there is no true "connected right now" — the pill shows the one thing the server actually knows, the time of the last authenticated call, and never pretends otherwise.
* The timestamp is a durable latch recorded beside the existing first-contact latch on every authenticated request (throttled to one write a minute), so it survives the 200-row activity log aging out or being switched off. The Connection tab's status line reads the same latch and no longer claims a bare "connected" with no time on long-idle sites.
* Uninstall removes the latch; new self-test checks pin the recorder, the reader, the pill states and the cleanup.

= 1.6.1 =
* THE ADVERSARIAL AGENT SWEEP, ROUND TWO — four independent review agents against the whole surface; twelve confirmed findings, all fixed same-day.
* PAYWALL: a crafted request could run a Pro site-level fix (noindex, permalinks, template images) on Free by riding any page id past the gate. Both doors — wp-admin AJAX and the MCP tool gate — now ask the fixer's own dispatch whether a check is site-wide.
* FIX ALL: an apply must now present the plan token of the plan it displayed; the 1.4.2 allowance for a token-less apply protected nobody (the script cache-busts on every release) and let the staleness check be skipped.
* TOKENIZE: the verify step scanned the whole page for swapped literals while the swap correctly touches only block-attribute JSON — a page that also DISPLAYS one of its colours (a code sample, a style guide) rolled back a clean write with an error, every time. The verify now reads exactly what the swap wrote.
* CONTRAST: rgb() channels above 255 clamp to what the browser will actually paint — an overdriven "white" could previously rate above real white and slip a below-AA colour past the review's gate.
* TYPE SPECIMENS: the mined-convention and token phrasings now render specimens too — the 1.6.0 regex only matched the adopted-design-system phrasing, so the most common source of this finding drew nothing.
* SEO LENGTH CHECKS measure the decoded title and description — the same ruler as the search preview — so an &amp; no longer counts as five characters and the check can never contradict the card beneath it.
* SCORE DELTA: "since X ago" now reads the score history's own clock; on a non-UTC site it was off by the site's whole UTC offset.
* FIX BUTTONS SURVIVE ERRORS. A network blip or an expired session removed the control until a full page reload; every error path now restores the button with the reason beside it. Server refusals that spoke a different field name now reach the UI instead of a generic fallback.
* REVIEW PANELS load once — toggling a panel mid-load no longer fires a second fetch that wipes what you were typing — and one audit chunk loop runs per screen, so Continue and Start over can no longer race the same cursor.
* FIX-ALL PLAN AND APPLY AGREE ON ARITHMETIC: the tokens plan counted distinct literals while the apply counted occurrences — "1 change" planned, "12 changes" written, for identical work.
* The review panels' fifteen hardcoded strings now pass through localization like everything else.
* New self-test group, Agent sweep, pins every one of these — behaviourally where cheap, by source needle where not.

= 1.6.0 =
* EVERY AUDIT SECTION SHOWS ITS FINDING, NOT JUST DESCRIBES IT. The alt-text and contrast reviews set the pattern; the rest of the panels catch up.
* SEO TITLE AND META FINDINGS RENDER THE SEARCH RESULT. "Title is 74 characters" becomes the actual result card with the last 14 characters dimmed exactly where Google cuts them — the same effective title and description the checks read, so the preview and the finding can never disagree. A missing title or description says what search engines will do instead.
* PERFORMANCE FINDINGS SHOW THE IMAGES. "3 image(s) over 300 KB: hero.jpg…" opens itself into the actual images — thumbnail, weight and width badges — with hotlinked or unmatched files listed honestly beside the reason nothing can compress them.
* HEADING FINDINGS SHOW THE PAGE'S OUTLINE. Every heading in document order, indented at its level, with a "level skipped" flag exactly where the jump happens and "extra H1" on every H1 after the first — the picture the heading checks were describing all along.
* TYPE-SCALE DRIFT RENDERS THE TWO SIZES AS TYPE. Aa at 19px beside Aa at 40px, so the change is seen before it is applied; display capped, labels truthful.
* A COLOUR NAMED IN ANY FINDING SHOWS ITSELF. Every hex in every finding carries a small swatch dot painted that exact colour.
* New self-test group, Section visuals, pins each of these against fixtures — truncation points, outline flags, hotlink refusals, size caps.

= 1.5.0 =
* FIX ALT TEXT WHERE YOU SEE IT. Missing-alt findings no longer hide the review behind a click: the panel opens itself, so the row arrives with the image thumbnail, the best suggestion pre-filled, and the input ready — describe the picture and Apply, right there. The Review images button becomes a hide/show toggle, the Open in builder link stays for anyone who wants the full page around the image, and a page with many findings loads the first dozen and opens the rest on click.
* EVERY AUDIT PILL SAYS WHEN IT LAST RAN. "Should I re-run?" used to mean reading one sentence inside one section at a time; now each of the six pills carries a compact age — 35m, 3h, 6d — with the full time in the tooltip. A run older than a week, or an audit never run, shows amber, because that is the point at which the counts on the pill stop describing the site.

= 1.4.3 =
* The contrast review's suggested-swatch caption failed contrast on light backgrounds — the label sits on the pair's own colour, so it now rides in a solid dark chip that is legible on anything. The one screen about contrast no longer fails it.
* The type-scale finding leads with a human sentence ("Fix snaps this heading back to the size named above") so Simple mode has something to say before the tool path.

= 1.4.2 =
* THE QA AGENT SWEEP, FIXED SAME-DAY. Three independent adversarial reviews ran against the 1.4.x code; thirteen findings survived verification and every one ships fixed here.
* Contrast review: BOTH halves of a pair are identity now — an approval made for one text colour refuses to overwrite a colour an editor chose after the list was made (the background already refused; the foreground did not). Colour parsing is anchored, so a value with trailing junk after a valid colour is no longer "a colour"; and alpha detection now knows every alpha spelling (space syntax, percent), so a translucent replacement can never be rated as opaque, pass AA, and silently make the page worse.
* Site QA: the broken-token FAILURE cause no longer draws the tokenize button — an invented token id needs a human to pick the real token, and the row now says so instead of dead-clicking or claiming success for work it never did.
* Legal: the publish guard also recognises WordPress core's own auto-created Privacy Policy draft ("Suggested text:" sections) and refuses to publish template boilerplate under your business name.
* Fix All: the confirm click is cryptographically bound to the plan it displayed — if the stored audit changes between plan and confirm, the write is refused and the button re-plans. A refused site-wide fix no longer renders in success green, an error no longer strands the plan list on screen, and the plan's aggregate now counts what it found instead of reporting zero.
* Score delta: a movement caused purely by waiving findings now says "waived findings N → M" instead of blaming coverage.
* Simple mode: two design tokens in one sentence no longer swallow the words between them; findings on draft pages link to the editor (the Visual Builder front-end link 404s on drafts); the plan-confirm strings joined the translation table.
* Nine new self-test pins hold all of it.

= 1.4.1 =
* Design → This site's system: a SHADOW role's value rendered as its raw JSON in a cell that could not wrap, which made the whole adopted-roles table wider than its card and pushed the Override column off the screen for every row. Shadows now read as the shorthand a designer knows — offsets, blur, spread, colour — with the exact stored object in the tooltip, and the value cell is allowed to wrap. Caught live minutes after 1.4.0 shipped; render-only, no behaviour changes.

= 1.4.0 =
* EVERY AUDIT PANEL CATCHES UP TO DESIGN GUARDIAN. A panel review of the product asked one question of each audit: can I understand what is wrong AND fix it without leaving the panel? Guardian answered yes; the other five now do too.
* CONTRAST GETS A REVIEW SCREEN WITH SWATCHES. Each failing pair renders as it actually is — the text colour on its real background — beside the nearest colour from this site's OWN palette that clears WCAG AA, as a second swatch with its ratio. Approve it, or type your own; typing previews live. An approved suggestion writes the design-system TOKEN, not another literal; a replacement that would itself fail AA is refused with the ratio it would have had; the site-wide Link Color pairs say why one module cannot fix them. Journaled and undoable like every write.
* SITE QA'S "HARDCODED VALUE" WARNINGS GROW A FIX. One click routes the page through the tokenize engine: every literal matching exactly one design-system colour becomes that colour's token, verified literal-for-token with zero modules lost, prior content preserved. Ambiguous literals — one value, several tokens — are listed with their candidates, never guessed.
* FIX ALL SHOWS ITS PLAN FIRST. The first click runs the batch dry and lists, page by page, what would change; the button re-arms as the confirm, and only the second click writes. The engines have planned like this since 0.69.0 — the button just never showed anyone.
* OPEN IN BUILDER, EVERYWHERE. Every finding row (and every single-page cause) links straight into the Visual Builder on the page it names, so "Node 0.4.1.0.1" stops being a coordinate you cannot visit.
* SIMPLE MODE FINALLY REACHES THE FINDINGS. In Simple view, token JSON reads as its label ("use the DA Sky token") and sentences that speak tool — divi_edit_module, attribute paths — step aside; Advanced shows the engine's exact words, unchanged. Nothing is ever hidden entirely.
* THE SCORE DELTA EXPLAINS ITSELF. "−1 since yesterday" is now a disclosure: open it and it names which audits moved — failures and warnings, from → to, per audit — from per-suite snapshots the score history now keeps. An audit counted for the first time says so, rather than reading as new damage.
* LEGAL DRAFTS PUBLISH FROM THE PANEL — with the one guard that matters: a document still carrying [REVIEW] placeholders is refused, because a live legal page with blanks in it is worse than a missing one.
* Site-level findings with no button get a door instead of a dead end (e.g. "no SEO plugin" links to the plugin browser).
* New self-test group, Panel catch-up: refusals first (still-failing colours, changed backgrounds, unknown documents), then the writes, then the undos.

= 1.3.10 =
* ALT TEXT GETS A REVIEW SCREEN. The automatic fix fills from the Media Library and refuses to invent — correct, and it left the images that most need a human (no library alt, external file, renamed upload) as unactionable "skipped" rows in a response nobody reads. The audit's missing-alt findings now carry a Review images button: each image is shown in the row, the best default is pre-filled where one exists, and the human approves it or types their own. Writes go through the same journaled, undoable path as every other fix, and an approved item is refused if the image changed since the list was made.
* DESIGN GUARDIAN GROWS FIX BUTTONS — all four checks. The audit as it stood was warnings that never moved and never offered a hand. Missing and duplicated H1s route to the headings engine, which already promotes under guards and demotes duplicates. Auto-rotating sliders get autoplay switched off in stored attributes — arrows, dots and swipe all keep working; the slider just waits for the visitor. Heading sizes drifted off the site's own resolved type scale snap back to it, against the same adopted/token/mined sources the check fires against and never the shipped default.
* Generic CTA copy is review-only, deliberately. No rule writes a good button label, so the one-click path writes nothing and says so; Review copy shows each button, its current text, where it links, and a mechanical suggestion (an internal link becomes "See {that page's title}") for the human to approve or rewrite. A replacement that is itself on the generic-copy list is refused — a fix that re-flags on the next audit fixed nothing.
* Review writes carry every gate a Fix click carries — the free tier's bound page rule included — because a review screen must not become the door the paywall audit keeps finding open.
* Guardian fixes journal under taste, not perf, so the journal reads as what happened.
* New self-test group, Review fixes: the list offers what the page really holds, empty and stale items are refused with reasons, the CTA one-click stays inert, and every written fix undoes.

= 1.3.9 =
* THE PAYWALL COULD FAIL OPEN, and it was a fix in 1.3.8 that did it. 1.3.8 made DVC_License::free_page() heal a binding whose page had been deleted, so a stale binding would stop refusing every write for a reason nothing on screen explained. That read is what page_gate() calls on every single tool call, and page_gate does no existence check by design — it compares ids. So a binding whose page could not be resolved became NO binding, and the gate waved all 21 page-scoped tools through onto any page. A paywall that heals itself into having no limit is worse than the stuck state it was fixing: it fails open, and silently.
* The self-test caught it on the first run after the deploy — eight failures in Licensing & tiers, including "a second page is refused" reporting NO ERROR — FREE TIER REACHED A SECOND PAGE. It never reached a customer. This is the whole argument for the suite existing.
* free_page() is a pure read again. The healing moved to the Overview screen, where a human can see it happen: a binding pointing at a deleted page now says so, offers to release it, and does not charge that release against the three-rebind cap — charging someone for a mess the plugin made would be its own small insult.
* The two new wp-admin paywall pins from 1.3.8 had windows too tight to survive the comments explaining them, and reported a false failure. Widened. A pin that fails because somebody documented the code is a pin that gets deleted.

= 1.3.8 =
* LICENSING PASS BEFORE LAUNCH. Two paid capabilities were reachable without a licence, and the limit the whole Free tier rests on had no floor under it.
* THE CLIENT REPORT WAS ONE UNGATED CLICK. DVC_Report::download() had a capability check, a nonce and no licence check at all, and the button was drawn on every one of the six audit screens, on every tier, in the default view. divi_export_report was gated correctly; this produced the identical artifact through a different door. Free deliberately gets the whole site-wide audit, so a Free install had complete findings and one click turned them into the branded deliverable an agency resells. This is the seventh leak of the family 1.3.3 closed six of.
* The wp-admin door is now covered as a CLASS in the self-test, which is why the seventh survived: 1.3.3 fixed six handlers one at a time and nothing pinned the shape of the problem. The licensing group now asserts that every paid admin action carries its guard, that the report download is gated, that the report button is not drawn to a tier that cannot use it, and that fixing and restoring in wp-admin both respect the free page binding.
* THE FREE PAGE WAS A REVOLVING DOOR, AND THE REFUSAL EXPLAINED HOW TO USE IT. Releasing the binding was a bare delete with no counter and no cap, and the message the agent receives named wp-admin as the place to do it — so Claude relayed it as the sanctioned remedy. Release, build the next page, release again. That leaked far more than the eleven automated fixes: divi_create_page and every surgical editor are page-scoped free tools, so it reopened the exact hole page_gate() was hardened to close, at one click per page. Rebinding is now capped at three — enough for someone who bound the wrong page on their first call, nowhere near enough to walk a site — and the sentence naming the workaround is gone.
* Restoring a page revision from wp-admin ignored the free page binding, while the same capability was bound on the tool surface. Little revenue rode on it, but an invariant that holds on one door and not the other is not an invariant.
* THE SEATBELT CAME BACK OUT FROM BEHIND THE PAYWALL. 1.3.3 moved divi_restore_snapshot to paid, reasoning that a free install cannot change the design system so has nothing to restore. True in steady state, false in the two cases where a rollback matters most: a trial grants full Pro, so a trialist can rewrite the whole palette and then drop to Free holding snapshots they can no longer use, and a lapsed customer is in the same position — while taking a snapshot stayed free the entire time. A pure rollback can only return state the site already had and nobody buys a licence for it. Restoring the design system from wp-admin, and releasing an adopted one, are free again for the same reason. The real 1.3.3 fix is untouched: it is still in DESIGN_TOOLS, so "Protect the design system" still covers it. Free tools are 43 again, Pro 43.
* The scheduled-audits form rendered in full on Free and refused at the save, discarding what had been typed. It is now a locked card that says it is Pro before the effort, the same treatment Fix-all already had.
* Client report links expire and nothing said so. Every save prunes reports older than 14 days, so a monthly schedule was deleting last month's report — including the link an agency had already forwarded to a client. The result and the digest email both say so now.
* A lapsed licence left the schedule toggle showing ON beside "Nothing scheduled", and the activation hook re-armed the cron on any deactivate/reactivate cycle. The state is written down when the licence check unschedules it.
* A free page binding pointing at a deleted page refused every write with no visible cause. It now heals itself, and costs no rebind.

= 1.3.7 =
* FIRST-RUN PASS. Somebody who has just installed this and has no idea what MCP is was walked through the plugin screen by screen, and every place they got stuck was fixed.
* The Connection screen now states the prerequisite nothing stated: you need a Claude account on a plan that can add custom connectors. Not the plugin, not either readme and not one page of the marketing site said so, so the failure mode was buy it, install it, read a green "Ready", follow all five steps, and find out at step two that the account cannot do it — having been told the whole way that everything was working. It links to Claude's own page rather than naming plan tiers, which change.
* "Didn't attach? Run the connection checks" now sits under the last step, and only while the site has never been connected. Diagnostics is Advanced-only by design, and Simple is where a new install starts, so the one person who needed the connection checks was the only one who could not see them. The button promotes the view and lands on the checks in a single click.
* Connection reports whether Claude has actually called in, and when. "Endpoint live" only ever meant the REST route answers; the plugin already knew the difference — it is what the first-flight checklist reads — but the fact was not on the screen where somebody had just pasted a URL and wanted to know if it worked.
* The audit opens the most severe group you actually have, instead of only opening failures. Grouping by cause rather than by page is the best idea in this product, and on a site with warnings and no failures every group rendered closed, so a first-time visitor saw one line of small text above two shut rows and no hint a Fix button lived three levels down.
* "How this is scored" on the Overview score card. The reasoning — a failure counts as six warnings, accessibility and legal weigh half again for liability, design taste weighs half because its findings are opinions — was written out in full in divi_get_score's description, where only Claude ever read it. The person looking at the number was the one not being told.
* The waived-findings line read like a rendering bug: "5 findings are not counted in this score (5 by design)" is the same digit twice in a sentence that seems to repeat itself. It now names the mechanism once, says who did it, and links to the findings.
* The safety switches no longer look saved when they are not. Their Save button sits at the top of a card you scroll down through, so flipping "Read-only mode", watching it animate and navigating away was easy — and those switches decide what an AI may do to a live client site. The button is inert until something changes, and leaving with changes pending asks first.
* The rescue fix plan's first line told the agent that divi_snapshot was the rollback point every later step assumed. It is the design-system snapshot, not page content. It now says what it does cover, what it does not, and that neither replaces a real backup before a migration that size.
* "Rebuild index" says what index. The design counters are read live from Divi on every render and that button has never touched them; it re-reads Divi's module definitions after a Divi update.
* Dropped "MCP" from the first sentence of the Connection screen. It was the first acronym a Divi customer met and it was expanded nowhere in the product.

= 1.3.6 =
* THREE WRITES THAT KEPT NO STEP BACK, one of which said it did. 1.3.4 closed this hole on the two page-content writers and did not sweep the rest of the file.
* divi_repair_preset_tokens with scope=tokenize rewrote colour literals across every module on a page, called wp_update_post() directly, and returned "A revision holds the prior content." There was no preserve_prior() and no wp_save_post_revision() in the function at all. False on every site, not only the ones with revisions disabled, and it is the widest-blast-radius page write in the plugin. It now preserves first and reports which kind of step back it made.
* Theme Builder slot writes and Divi Library writes called a bare wp_save_post_revision(), which does nothing on a site with WP_POST_REVISIONS off. A header write there had no undo of any kind — and one bad header write is every page on the site. Both now go through preserve_prior(), and both results say where the step back is. A global Library layout write, which changes every page referencing it, was the highest-blast-radius write in the plugin with no fallback behind it.
* The self-test now says when a run was short of full coverage. Four groups — Accessibility engine, Theme Builder, Divi Library and Content coverage — need Divi's builder framework, which wp-admin does not load, so they are skipped there and run through the connector. Both surfaces already behaved correctly and each wrote a "Skipped" row, but the wp-admin headline read "All 1,494 checks passing" while the same suite reported 1,673 through the connector, with nothing on screen explaining the ~180 difference.
* The rescue scan's page lists are capped at 40 per bucket while its counts are complete, so a site with 200 Divi 4 pages was told 200 and handed 40 ids with nothing saying so. The result now reports lists_capped with the shortfall per bucket and what to do about it. The existing scan_capped covers the 300-page scan cap and was being read as covering this one too.
* "Every finding has a one-click fix" on the first-flight checklist. There are 83 check types and 11 of them have a Fix button. That is step four of the checklist an evaluator reads in their first ten minutes.
* Two strings still described tier gating as shipping OFF, which stopped being true in 0.90.0. One of them is in the licence status payload that divi_get_site_context returns, so Claude was being told the paywall was unwired at the start of every session.
* The fixes tile named alt text and headings and hid the other nine fixable checks — image compression, page weight, and the SEO meta and noindex fixes are all journaled and individually undoable too. 1.3.5 over-corrected this one.
* The connector URL is described honestly: it survives updates and deactivation, but uninstall.php deletes the key by design, so deleting the plugin does issue a new URL.
* Corrected against the code: the undo journal keeps 100 fixes, not 30; the rescue tool description said "classifies every page" where every other surface says up to 300; the design-system sniffer discloses its 300-item cap to the agent, not only in its output; the rescue tile read as though the scan converts pages, when it produces a plan Claude then works through; four more tool descriptions promised a revision where preserve_prior() may have used the undo slot instead; the Autopilot Site Score rename reached divi_get_score, both readmes and the onboarding checklist; and the checklist said six auditors read every page where five do and legal reads the site.

= 1.3.5 =
* The score is now labelled "Autopilot Site Score" on the Overview dashboard. "Site score" read like a WordPress feature; it is this plugin's arithmetic and it should say so.
* The dashboard's own capability copy carried the same overstated claims that were just corrected on the marketing site, which is worse — this is the copy an evaluator reads while deciding whether to trust the thing. All four are now what the code does: fixes say alt text and headings are journaled and undoable while legal pages arrive as drafts to review; the safety-net tile says one step back before every page write and a snapshot before every design-system write; rescue says up to 300 pages instead of "every page"; and the audit tiles say five auditors read every page while legal reads the site.
* Same correction on the Audit and Rescue screens' own intro text.

= 1.3.4 =
* FIXED, and it is the one that matters most: the step back kept for sites with WordPress revisions disabled was written and unreachable. preserve_prior() stashes the outgoing page content in post meta when wp_save_post_revision() will do nothing — WP_POST_REVISIONS off, which several managed hosts ship and which every "optimise your database" plugin offers — and then told the operator to restore it with divi_restore_revision using revision_id 0. There was no branch for 0. get_post(0) is null, so the answer was "Id 0 is not a revision." prior_undo(), the function that reads the slot back, had no callers anywhere in the plugin, divi_list_revisions never listed it, and the dashboard never rendered it. On exactly the sites least likely to have another backup, the recovery instruction was false.
* divi_restore_revision now accepts revision_id 0 and restores the undo slot, with the same dry run, the same module-count verification and the same refusal to touch another page's content as any revision restore.
* divi_list_revisions lists the slot as its own row, id 0, first, with its module count and its own note explaining what it is — an unexplained row in a restore list is worse than no row. The response also reports has_undo_slot and whether this site stores WordPress revisions at all.
* Restoring is now undoable on both kinds of site. The restore path called wp_save_post_revision() directly, which does nothing where revisions are off, so restoring the slot consumed the only step back and left none. It goes through preserve_prior() now, and says which of the two kinds of undo it made. Restoring the slot twice toggles rather than repeating.
* History in the dashboard shows the undo slot with an "undo slot" pill, and the confirm text no longer promises a revision it may not be able to save.
* Three tool descriptions and the History screen's own note claimed "every write saves a revision first". True on most sites, false on the ones this feature exists for. All now state what actually happens.
* New self-test group, "Undo slot", which writes the slot the way a revisions-off site would and drives the whole round trip. The bug survived because every test ran on a site with revisions ON, where the slot is never written.

= 1.3.3 =
* SECURITY/LICENSING: the paywall was enforced on the MCP tool surface only. Six capabilities sold as paid were one ungated click away in wp-admin — fixing a cause across every page, scheduled audits and the emailed client report, installing legal drafts, adopting a design system, overriding a design role, and restoring the design system. All are now gated on both surfaces, and the scheduler refuses to arm or to fire without a licence so a lapsed site stops rather than quietly continuing.
* Fixing from wp-admin now respects the Free tier's bound page, the same rule the tool surface applies. Previously any page could be fixed from the audit screen regardless of the binding.
* divi_restore_snapshot joins the design-system tool group, so "Protect the design system" now covers it. It rewrites colours, variables and presets site-wide and was the one write that switch could not see. It is now a paid tool, alongside the rest of the design system.
* divi_snapshot, divi_restore_snapshot and divi_check_legal have left the page-scoped free list. None of them accepts a page argument, so the page gate could never bind them — membership read as a guarantee and was decorative. The self-test now asserts against each tool's real schema instead of a hand-built argument array, which is why this went unnoticed.
* Free tool count is 42, not 43 (divi_restore_snapshot moved to paid). The readme said 43 and the README said 42; both now say 42.
* One icon set across the plugin and the marketing site. The dashboard's ten capability icons were Unicode glyphs from six different blocks, two of them emoji codepoints that the operating system rendered in colour while the rest stayed monochrome — so the same screen looked different on macOS, Windows and Linux. All are now inline SVG on one 24px grid.
* New "Next" row on Overview: at most three tiles naming the next action and what it does, ordered by what blocks what. The capability map below it is a catalogue; this is the direction.

= 1.3.2 =
* Fixed: every surgical write — divi_edit_module, divi_add_module, divi_move_module, divi_delete_module — was returning the whole page's token digest, not the warnings for the node you just wrote. On a real build, forty consecutive edits each came back with the same eleven hardcoded-value warnings and their full node lists, unchanged. That is tens of thousands of tokens of an agent's context spent restating what it was told on the previous call, with the one warning that belonged to the edit buried in the middle. divi_update_page was deltaed when this was first diagnosed; the surgical writers, which are the ones called in a loop, were not.
* New warnings still come back in full. Pre-existing ones collapse to a single counted line naming divi_validate_markup for the whole list. A page with no prior content — divi_create_page — still returns everything.

= 1.3.1 =
* Fixed: the full self-test reported eight failures on a Free site when nothing was wrong. Six were the licence gates correctly refusing paid writes, and two were an adopted design system correctly outranking the miner. Every one of those refusals is now asserted as the correct behaviour it is, on both tiers.
* The full suite is meant to be run from wp-admin on any tier. It now stays green there whether or not the site is licensed, and whether or not a design system has been adopted.

= 1.3.0 =
* Reads the design system your site already has. Scans pages, posts, Theme Builder layouts and the Library — presets resolved, newest work weighted heaviest — and proposes your real colours, type, radii, shadows and spacing as a scale rather than an inventory. Adopt it and Claude resolves every design question against it first.
* Four new resolver domains — elevation, radius, spacing, sizing — that answer with a paste-ready Divi 5 attribute fragment at the correct root for the module you name.
* Group presets are now resolved when auditing. Styling that lived only in a group preset was previously invisible to the contrast, accessibility and performance engines.

= 1.2.0 =
* Licence keys can be activated after the fact: a masked key field on Diagnostics -> Licensing, a one-line prompt on Overview, licence detail with seats used, and a "release this site" control so a seat can be moved.

= 1.1.0 =
* Admin UI translated into French, German, Spanish, Italian, Brazilian Portuguese, Dutch, Polish and Japanese.

= 1.0.2 =
* Findings table readability: primary finding text at full contrast (10.2:1).

= 1.0.1 =
* Self-test reliability: content-classifier checks made deterministic across WordPress parser versions.

= 1.0.0 =
* Commercial launch. Tier enforcement on by default; GPL license file; pre-launch security audit fixes (design-guard bypass closed, uninstall data hygiene, endpoint rate-limiting, log secret-scrubbing).

= 0.98.x =
* Unreadable-content architecture: audits declare what render-time modules they cannot read instead of reporting false counts or false cleans; API-key leak in page rendering closed.

= 0.91–0.97 =
* Site score with disclosed arithmetic, per-finding owner waivers, first-flight onboarding, auto-continuing chunked runs with progress.

== Upgrade Notice ==

= 1.8.2 =
Theme Builder fix found by dogfooding: templates created over MCP stored conditions Divi never resolved (they showed "Unassigned" in the Theme Builder UI), and body-only templates swapped the global site header for the theme's stock one. Both fixed; loop-field tokens also no longer trip a false validator warning. If you created a template through the connector before 1.8.2, open Divi → Theme Builder once to confirm its assignment.

= 1.8.1 =
Audit accuracy fix found by dogfooding our own blog: Gutenberg and classic-editor content was invisible to the collector, so posts measured zero headings and zero internal links and the SEO audit reported a false "no internal links" warning on them. Blog-heavy sites should re-run their audits after updating — expect warnings to disappear, not appear.

= 1.8.0 =
Fixes now re-check the page they touched, so audit numbers stay current instead of describing a page that no longer looks like that. And client reports can carry your own name and logo — Settings → Client reports, available on every paid plan.

= 1.7.3 =
Licensing fix: deleting the plugin now tells Freemius, so your licence seat is freed for the next site instead of staying burned. The cleanup sweep is unchanged in what it removes — it just runs on the uninstall hook now, which also lets multisite subsites clear their cached transients.

= 1.7.2 =
Cleanup hardening: test-fixture pages stranded by interrupted runs on earlier versions could show up in your audits as SEO and QA failures on pages you never made. They are now titled under the swept prefix, and leftovers from earlier versions are reclaimed automatically on the next self-test run.

= 1.7.1 =
Hosting fix found by dogfooding on WP Engine: chunked self-test runs could loop forever at the same cursor on hosts with a persistent object cache, because the run lock was a cache-only transient that eviction could erase mid-pause. The lock is now database-backed and the whole pause/resume round-trip is cache-proof.

= 1.7.0 =
A connection pill in the header of every screen shows when the site last heard from Claude — green while active, amber after a silent week, grey when never connected — so connected vs disconnected is visible at a glance instead of taken on faith.

= 1.6.1 =
Hardening from the second adversarial agent sweep: a Free-tier paywall bypass on site-level fixes closed on both doors, the tokenize verify no longer rolls back clean writes on pages that display their own colours, contrast math clamps rgb() channels the way browsers do, type specimens render for all three finding phrasings, SEO length checks measure what a searcher sees, and fix buttons survive transient errors instead of vanishing.

= 1.6.0 =
Every audit section now shows its finding: SEO findings render the search result cut where Google cuts it, performance findings show the offending images with weight badges, heading findings show the page outline with the breaks flagged, type-scale drift renders both sizes as type, and every hex named anywhere carries its own colour dot.

= 1.5.0 =
Missing alt text is now fixed in place — the finding arrives with the image, the suggestion and the input already open — and every audit pill shows when it last ran, going amber when the run is stale.

= 1.4.3 =
Cosmetic: the contrast review's own swatch caption now passes contrast everywhere, and the type-scale finding reads human-first in Simple mode.

= 1.4.2 =
Same-day hardening of 1.4.0's new surfaces after an adversarial review sweep: contrast review refuses stale approvals on both halves of the pair and can't be fooled by junk-suffixed or translucent colours, Fix All's confirm is bound to the plan it showed, the legal publish guard knows core's template draft, and the broken-token cause stops offering a fix that couldn't fix it.

= 1.4.1 =
Render fix for Design → This site's system: shadow roles no longer blow the table off the screen. Update straight past 1.4.0.

= 1.4.0 =
Every audit panel catches up to Design Guardian: contrast fixes with before/after swatches from your own palette, one-click tokenizing for hardcoded values, Fix All shows its plan before writing, every finding links into the Visual Builder, Simple mode stops speaking tool, the score delta names which audits moved, and legal drafts publish from the panel (unless they still carry [REVIEW] blanks).

= 1.3.10 =
Design Guardian grows Fix buttons on all four checks, and missing alt text gets a review screen — the image shown in the row, the plugin's best default pre-filled, your own words taken instead. Everything journaled and undoable.

= 1.3.9 =
Supersedes 1.3.8 — do not run 1.3.8. A fix in it made the free-tier page limit fail open when the bound page had been deleted, waving every page-scoped tool onto any page. Caught by the self-test before it reached anyone, but 1.3.8's zip was published, so this replaces it.

= 1.3.8 =
Licensing fix — update before you sell anything. The client report was downloadable without a licence, and the Free tier's one-page limit could be released and rebound without limit. Also returns snapshot restore to the free tier: a rollback should never be behind a paywall.

= 1.3.7 =
First-run pass. The Connection screen now states that you need a Claude account on a plan that supports custom connectors — the prerequisite nothing stated — and offers a way into the connection checks when it does not attach. No behaviour changes to any write path.

= 1.3.6 =
Recovery fix, and it affects Theme Builder and Library writes. Three write paths kept no step back on sites with WordPress revisions disabled, and one of them claimed it had, on every site. Update before letting anything write to a header, a footer or a global Library layout.

= 1.3.5 =
Copy only, no behaviour change: the score is now "Autopilot Site Score", and four dashboard claims that overstated what the plugin does have been corrected to match the code.

= 1.3.4 =
Recovery fix. On sites with WordPress revisions disabled, Divi Autopilot saved a step back that nothing could restore, and told you to restore it anyway. Now restorable, listed, and covered by its own self-test group. Update if any site you run has WP_POST_REVISIONS off.

= 1.3.3 =
Important licensing fix: six paid capabilities were reachable from wp-admin without a licence. If you sell this plugin, update. Also unifies the dashboard icon set and adds a Next-steps row to Overview.

= 1.3.2 =
Context-efficiency fix for anyone driving Autopilot from an agent. Surgical edits now report only the warnings that edit introduced, instead of re-listing the whole page's token digest on every call. No functional change to what is written.

= 1.3.1 =
Self-test accuracy fix. Recommended for every Free install: the previous release reported its own paywall as eight failures. No functional changes.

= 1.3.0 =
Adds site design-system extraction and four new design domains. No breaking changes; nothing is adopted until you adopt it.

= 1.2.0 =
Adds a licence key field for customers who bought Pro after installing Free. No breaking changes.

= 1.1.0 =
Adds nine admin languages. No breaking changes; settings and runs carry over.
