# wp-plugins/mega-ai/

The MEGA AI WordPress plugin. Customers install this on their site;
it exposes the `/wp-json/mega/v1/*` REST endpoints the bot writes
through. Distributed via the **WordPress.org plugin directory**
(`https://wordpress.org/plugins/mega-ai/`); updates flow through
WP core's native update path.

## Version contract

The canonical version lives in **two places that must stay in sync**:

- The `Version:` plugin header at the top of `mega.php` (read by
  WordPress core, by `readme.txt`'s `Stable tag`, and by the
  WP.org SVN auto-deploy workflow).
- The `private static $version` constant inside `MegaPlugin` (used
  by the runtime to report version through `/wp-json/mega/v1/version`).

If you bump one, bump the other. Bump `readme.txt`'s `Stable tag`
to match. Semver: feature → minor bump, bugfix → patch bump.

## Diagnostic safe-mode on `update_page()`

`POST /mega/v1/pages/<id>` accepts an optional `?diagnostic=1` query
param. When set, the handler SKIPS the `update_post_meta($id,
mega_managed, '1')` write. Reason: the MEGA SEO platform's CMS
diagnostic worker runs a non-destructive text-revert probe (append a
marker → restore the original content) against the customer's most-
recent published page, and without the flag every probed page would be
permanently tagged as MEGA-owned just because we observed it. Production
write paths (real bot publishing) call WITHOUT `diagnostic=1` so the
tag still gets set on legitimate writes.

If you add a new probe path that writes to live customer content, mirror
this pattern: a `diagnostic=1` opt-in on the side-effect (ownership,
indexing, audit-log, etc.) so the probe stays observably non-destructive.
DO NOT add the side effect globally and add `diagnostic=1` as a kill-
switch; the default behavior should be "probe touches nothing else."

## DO NOT re-add a self-update mechanism

Versions 1.5.1 → 1.6.0 shipped a self-update mechanism that polled
`https://app.gomega.ai/api/wp-plugins/mega-ai/update.json` and let
WordPress download + execute new PHP from a `download.zip` endpoint
hosted on `app.gomega.ai`. **It was stripped in 1.6.1 because it
violates WordPress.org Plugin Directory guideline #8 — "No External
Code".**

What the violation looked like in practice:

- A non-WP.org `Update URI:` plugin-header line.
- A `pre_set_site_transient_update_plugins` filter
  (`inject_update_manifest`) that fetched the manifest, compared
  versions, and injected a `response[]` entry pointing to our
  `download.zip`.
- A `plugins_api` filter (`maybe_serve_plugin_info`) that served
  "View details" thickbox metadata.
- An `$allowed_package_hosts` array, transient cache, and
  manifest-fetch helpers that supported the above.

How we found out: WP.org silently paused publishing 1.5.1, 1.5.2,
and 1.6.0 to the public plugin directory. SVN commits and the GH
Actions workflow succeeded; the directory page just froze at
1.4.0 (the last version that predated the self-update code).
`https://api.wordpress.org/plugins/info/1.0/mega-ai.json` is the
authoritative version source — it lagged SVN for the same reason.

**If you find yourself wanting to re-add a self-update flow, the
answer is no.** The plugin's WordPress.org listing is the only
stable distribution channel. To ship a new version: bump the two
version locations + `readme.txt`'s `Stable tag` + add a `Changelog`
entry, then merge to `main`. The
`.github/workflows/mega-ai-wp-deploy.yml` workflow auto-commits to
WP.org SVN. Expect a 24–72h indexing delay before the public
directory page updates.

## Distribution side (informational)

The `app/api/wp-plugins/mega-ai/update.json/route.ts` + `download.zip`
endpoints in this repo are still operational. They exist solely to
let any customer sites currently running 1.5.1, 1.5.2, or 1.6.0
(which were distributed via the now-removed self-update path) transition
forward to 1.6.1. Once the 1.6.1 plugin installs on those sites, the
`Update URI:` header is gone and WP core falls back to WP.org. After
the fleet finishes migrating off 1.5.1+, those msw endpoints become
vestigial and can be deleted.
