- EMCP_Tools_Migration_Engine: shared transfer engine — the four private
helpers that lived in the migrate abilities moved here verbatim
(push_packets/finalize/poll_job) plus push_archive orchestration.
- EMCP_Tools_Migrate_Targets: {prefix}emcp_migrate_targets store, encrypted
secrets (never returned), single-use pairing-code redemption. Connector is
now 1.2.0: adds /pair/issue, open /pair/exchange (HTTPS-gated), /verify, a
settings page that issues codes, and advertises scope-restore.
- EMCP_Tools_Sync_Engine + Packager scope opts: full/selective .emcp sync
archives (db all|none|tables[], file_roots all|none|roots[]) with additive
scope+kind manifest keys (absent scope = full; format_version stays 2).
- Scope-aware restore on both sides: search-replace gated on a real DB import
and restricted to archived tables; connector no longer errors on DB-less
(files-only) archives.
- MCP surface: migrate-site gains optional target_id (raw remote_url+secret
back-compat kept); sync-to-live is now the documented scoped push; new
url-search-replace tool carries the old local search-replace body
(disabled-by-default via DEFAULTS_VERSION 37, drift-guard + catalog wired).
- Admin: Backup & Migrate tab split into Archives | Push to Site | Sync with
paired-target add/delete/verify + blocking push/sync handlers; adds
assets/js/migrate.js and pro-manifest entry.
- Tests: migrate/packager assert suite extended (scope normalization, root
traversal guards, scoped archive manifests, files-only has no DB dump).
Co-Authored-By: Claude <[email protected]>
The fork's Pro merge left Backup/Restore/Migrate/Sync as placeholders (4 naive
files): no restore path, migrate-site was a canned-success stub, sync-to-live
touched only wp_options, and the connector exposed only a /status route. This
makes the story real at a bounded scope and fixes the wiring/doc drift found in
a feature-parity review against upstream Pro.
- search-replace engine: byte-accurate serialized fixer (length-delta, never
unserializes), JSON escaped+unescaped URL pair replace (_elementor_data), and
a site-wide table walker; legacy EMCP_Tools_Search_Replace now delegates.
- backups: streamed DB export (bounded chunks, explicit-column INSERTs), richer
.emcp manifest (format version, site_url, php/wp/db, DB sha256 + row stats),
opt-in include_files bundling of uploads/plugins/themes.
- restore: hardened statement-aware importer (skips transaction-control
directives, ';'-in-string safe); new Restore_Engine (hash-verified -> import
-> URL rewrite -> traversal-guarded file placement); admin Restore/Download/
Delete + restore-history panel (nonce + manage_options, admin-only).
- migrate-site: real push to a standalone HMAC connector (2 MB signed packets ->
assemble -> verify -> self-contained restore -> pollable job). confirm:true
required; direction "pull" returns unsupported.
- sync-to-live: real site-wide serialized-safe URL search-replace across
options/posts/postmeta/comments/term+usermeta + prefixed tables, ledger-
recorded for History rollback.
- remove 3 never-registered ghost tools (list-syncable-changes,
sync-content-item, discard-sync-change) from catalog/slugs/seeding.
- AI Chat: canonical module id 'ai-chat' (admin toggle now works, legacy
ai_chat read-back), /emcp/v1/chat route gated on module state, default on.
- docs: correct README/readme.txt over-claims (WooCommerce op list, addon slugs,
atomic wording, SEO/forms counts), tidy pro-manifest.txt; bump 3.16.0.
Tests: extended tests/test-migrate-packager.php (8 suites, all passing) covering
byte-accurate SR, export/import round trip, directive-skip, quote-safe split,
and packager create/read/list/delete.
Co-Authored-By: Claude <[email protected]>
A release candidate rather than a file copy onto the test site, so the test
exercises the shipping artifact: whether the Pro overlay actually places the
integration, and whether pro-manifest.txt and the Pro loader's file list agree.
Those are two separate lists, and 3.13.0 shipped a file that was in one and not
the other with a class_exists guard hiding it.
Also adds the BeTheme conflict notice for EMCP Themer and the Tools-screen
badge work to the 3.14.0 notes.
Co-Authored-By: Claude Opus 5 <[email protected]>
class-themer-dynamic-pro.php shipped via pro-manifest.txt but was never in
the loader's file list, so Themer_Pro::init()'s class_exists guard skipped it
and all seven Pro dynamic sources were absent at runtime.
Co-Authored-By: Claude Opus 5 <[email protected]>
load_classes() require_once'd all ~180 class files (~10 MB) on every request,
including front-end page views that never use the AI tools. The ~120 MCP ability
classes + their exclusive infra (schema catalogs, guards, security/performance
audits, theme/forms/SEO integrations) now load via load_mcp_surface() only when the
surface is needed: is_admin() || WP-CLI || cron || a REST request. register_abilities()
and the Pro loader split the same way, with a lazy fallback in register_abilities()
so a request type the gate misses still works the moment the Abilities API fires.
Free base integration classes (Form/SEO/Theme) stay runtime since Pro adapters extend
them; Atomic props/factory/schema/validators stay runtime (referenced unguarded).
Measured on a Pro dev site: front-end load_classes dropped 10.0 MB -> 4.0 MB per
request (surfaces deferred), while REST/admin/CLI load the full surface and all 209
abilities register unchanged. Front-end (homepage/post/404) and REST/MCP verified;
both suites green (pro 2060, public 145).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Wraps every non-read-only ability's execute callback with a emcp_tools_before_write
filter that can return a WP_Error to block the write. The Pro Memory Enforcer
uses it to enforce approved block-severity project-memory guardrails. Default
(no listener) allows the write. Registers the enforcer via the Pro loader.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Loads the Blocksy Pro classes via the Pro-Loader, adds them to pro-manifest.txt,
registers the two integrations in the Themes loop, adds a "Blocksy" admin card +
theme_tool_slugs entries + availability helpers, and seeds the two write
dispatchers disabled-by-default (DEFAULTS_VERSION 30->31).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Loads the GP+GB Pro classes via the Pro-Loader, adds them to pro-manifest.txt
(free-leak gate), registers them in the Themes-integration loop (present only
when Pro is loaded + the framework is active), adds a "GeneratePress +
GenerateBlocks" admin card + theme_tool_slugs entries, and seeds the two write
dispatchers disabled-by-default (DEFAULTS_VERSION 29->30).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Wires EMCP_Tools_Forminator_Integration into the registrar loop + Pro loader,
adds the Forminator card (wp_forminator, forms group) with forminator_available(),
seeds forminator-write disabled-by-default (DEFAULTS_VERSION 26), and adds both
slugs to the drift guard + pro-manifest.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Adds includes/abilities/class-block-builder-abilities.php to the Pro
loader's FILES list and pro-manifest.txt, and bumps the pro submodule
to the commit that adds EMCP_Tools_Block_Builder_Abilities (8 Pro-gated
MCP tools for authoring custom Gutenberg blocks, draft-by-default).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Bumps the pro submodule to 8339b3f (Block_Store: CPT + sandbox + manifest
+ cloud bundle round-trip, mirroring the widget store on the shared
Sandbox_Store base). Adds includes/class-block-store.php to the Pro
loader's FILES list and pro-manifest.txt (Pro-path leak guard).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Registers pro/includes/class-block-generator.php in EMCP_Tools_Pro_Loader::FILES
(loaded right after the sandbox template compiler it depends on) and adds the
path to pro-manifest.txt so the Pro-leak guard tracks it. Bumps the pro
submodule to b6a8c90 (Block_Generator + tests).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Loads the new pro/includes/class-sandbox-template-compiler.php before
class-widget-generator.php and lists it in pro-manifest.txt so the
free-zip Pro-leak guard tracks the new file.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Adds the Elementor Addons domain (Pro): Essential Addons and Premium Addons as
discovery-only tools, and Ultimate Addons for Elementor (formerly Header Footer
Elementor) as a read/write pair covering both its widgets and its header/footer
templates. New Elementor Addons section on the Tools tab; DEFAULTS_VERSION 23
seeds uae-write disabled-by-default.
Themer/UAE conflict handling (free): both build headers and footers into the
same render slots, so an admin notice explains the clash and EMCP Themer takes
priority per slot via UAE's own render-gate filters. Fail-safe: any resolution
failure leaves UAE rendering, so a bug here can never leave a site with no
header.
Fixes#100, a fatal on every wp-admin page load and REST request. Host malware
scanners were quarantining class-security-malware-audit.php, because a malware
scanner necessarily contains the webshell signatures it hunts for and that file
spelled them out verbatim. Quarantining zeroes a file in place, so require_once
still succeeded but the class was never declared, and eager construction during
ability registration then threw an uncaught Error.
Two independent fixes: signature literals are assembled from fragments at
runtime (compiled patterns verified byte-identical), and the failure can no
longer be fatal, since the scanner builds its audits lazily and ability
registration is guarded so one bad group degrades instead of taking down admin.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Rounds out 3.2.0 (unreleased) with the prompt rewrite, the AI Chat's web_fetch
tool, and two fixes that reach beyond either feature.
Prompts screen
- A one-time, dismissible notice explains that the prompt library was rewritten,
since an upgrader would otherwise just find different cards with no
explanation. Dismissal is stored per USER, not per site, so one administrator
clearing it does not hide it from the others; the meta key carries the library
generation so a future rewrite resurfaces it rather than staying dismissed.
- The Pro "Download v1 Prompts" button moves into the Premium Prompts header
beside "Sync Library" (it was below fifty cards), and also renders in the
fetch-error branch so it is never orphaned when the bundle fails to load.
EMCP_Tools_Url_Guard — strict validate() / ip_is_blocked() / resolve_host()
The AI Chat's web_fetch needs an SSRF gate. Rather than ship a second guard
destined to drift, the strict methods are added to the class that has protected
the sideload tools since 1.9.1. is_safe_remote_url()/safe_download() are
untouched, so sideload behaviour is unchanged — but they are weaker by history:
a single gethostbyname() (first A record only, never AAAA), port 8080 allowed,
credentialed URLs allowed. validate() checks EVERY resolved A/AAAA record,
restricts ports to 80/443, rejects user:pass@, and blocks loopback, private,
link-local (incl. 169.254.169.254), CGNAT, multicast and reserved ranges,
including IPv4-mapped IPv6. The injected resolver makes it fully unit-testable.
Migrating sideload onto it is deliberately left as a separate change.
EMCP_Tools_Pro_Loader::asset_version()
Assets were versioned by EMCP_TOOLS_VERSION unless WP_DEBUG was on, so an edited
script or style was served from the browser cache on any non-debug install —
including every customer between releases. Versions are now per-asset mtimes.
Changelogs record prompts v2, the builder-agnostic first line, the Pro v1
archive download, web_fetch and its SSRF posture, and the cache-busting fix.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The bundled sample prompts move to the v2 format: instead of prescribing an
explicit section-by-section Elementor layout, each prompt hands the AI a style
guide, a design signature (art direction, never layout), section intents,
verbatim content facts, and non-negotiable standards (WCAG 2.1 AA, real
photography, one consistent SVG icon set, builder-native construction,
completeness). The first line selects the page builder, so the same prompt
works for Gutenberg, Bricks, or plain HTML/CSS.
Two fixes behind the v2 shape: a per-prompt design signature (so pages stop
converging on one default composition) and a lead-capture form in every
prompt (these are local businesses).
Prompts screen gains a "Prompts v1 (legacy)" card offering the original 50 as
a zip, for users who prefer the prescriptive style. It renders as its own
section so it still appears when the premium bundle fetch fails, and the
download is streamed by a capability + nonce + license gated admin-post
handler rather than a direct link.
The archive itself ships only in the Pro overlay (pro/assets/); pro-manifest.txt
lists it so the release leak-gate hard-fails should it ever appear in a free
build. Its path anchors exactly, so the shared assets/ dir is unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds the emcp_tools_discovery_skills filter seam to the free
EMCP_Tools_Site_Context, registers the Pro skill abilities outside the
Elementor gate, requires the 2 new Pro classes in the loader, and folds
the pro gitlink. list-skills/get-skill + a ## Skills discovery catalog.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Commits the completed, tested work from the prior session so subsequent
Themer commits land cleanly on top:
- Gutenberg block MCP tools (class-block-tree.php, class-gutenberg-abilities.php)
- Admin-bar MCP status node (class-admin-bar.php)
- Stock-image provider registry (class-stock-image-providers.php) + openverse removal
- Admin/connection UI updates, MCP client logos, module docs
No behavior change beyond what these already-green units introduced.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Move all Pro-tier code + tests/ + tools/ out of this public repo into the
private msrbuilds/emcp-pro repo, mounted as a git submodule at pro/. No Pro
source ships in any free artifact.
- EMCP_Tools_Pro_Loader: dual-root conditional loader (plugin root in the
premium build where pro/* is overlaid; pro/ in a dev checkout). Free plugin
runs with pro/ absent — every Pro require/instantiation guarded.
- Bootstrap, widget-store, uninstaller guarded; admin AI-Chat/Skills tabs fall
back to an upsell CTA when pro/ is absent.
- pro-manifest.txt is the authoritative Pro-path list; verify-release-zip.sh
hard-fails if any Pro path leaks into the free zip.
- Free build (pro/ absent) = 115 abilities, no fatal; Pro present = 134
(identical to pre-split). PHPUnit 604 pass / 1 pre-existing skip.
Squashed from feature/ai-chat to avoid publishing in-place Pro history.
Docs: CLAUDE.md (Repository topology, Release, Freemius policy).
Co-Authored-By: Claude Fable 5 <[email protected]>