Title: AcrossAI Abilities Manager
Author: Deepak Gupta
Published: <strong>26. Juna 2026.</strong>
Last modified: 27. Augusta 2026.

---

Pretražite dodatke

![](https://ps.w.org/acrossai-abilities-manager/assets/banner-772x250.png?rev=3614045)

![](https://ps.w.org/acrossai-abilities-manager/assets/icon.svg?rev=3595583)

# AcrossAI Abilities Manager

 Od [Deepak Gupta](https://profiles.wordpress.org/raftaar1191/)

[Skini](https://downloads.wordpress.org/plugin/acrossai-abilities-manager.0.0.33.zip)

 * [Detalji](https://bs.wordpress.org/plugins/acrossai-abilities-manager/#description)
 * [Recenzije](https://bs.wordpress.org/plugins/acrossai-abilities-manager/#reviews)
 *  [Instalacija](https://bs.wordpress.org/plugins/acrossai-abilities-manager/#installation)
 * [Razvoj](https://bs.wordpress.org/plugins/acrossai-abilities-manager/#developers)

 [Podrška](https://wordpress.org/support/plugin/acrossai-abilities-manager/)

## Opis

AcrossAI Abilities Manager gives site administrators full visibility and control
over every ability registered via the WordPress Abilities API (`wp_get_ability()`).

**Features:**

 * **Browse all abilities** — a searchable, sortable, paginated table listing every
   registered ability with slug, provider, source, and current status.
 * **Toggle allow/disallow** — enable or disable any ability site-wide with a single
   click. Changes are saved instantly without a page reload.
 * **Edit ability metadata** — override `readonly`, `destructive`, `idempotent`,`
   show_in_rest`, `show_in_mcp`, `mcp_type`, and `mcp_servers` fields per ability
   using a tri-state system (Yes / No / Inherit from registry).
 * **Reset overrides** — restore any ability back to its registry defaults with 
   one click.
 * **Bulk actions** — allow, disallow, or reset up to 50 abilities at once.
 * **Ability Library** — enable or disable add-on ability groups from a dedicated
   Library page, with All/Specific mode controls per group.
 * **Add-ons page** — browse companion plugins from the WordPress admin. WordPress.
   org-hosted add-ons install / activate / deactivate in place; add-ons distributed
   elsewhere link out to the vendor's site so you can install them via Plugins  
   Add New  Upload Plugin.
 * **MCP server list** — view all registered MCP servers when the MCP Adapter plugin
   is active.
 * **Debugging  Conflict Testing** — toggle any installed plugin's _effective_ active
   state without ever writing to `wp_options.active_plugins`. Seven WP Abilities
   API abilities (`acrossai/conflict-test-list-plugins`, `-get-overrides`, `-set-
   override`, `-bulk-set-overrides`, `-clear-overrides`, `-deploy-mu-plugin`, `-
   remove-mu-plugin`) let a REST client, MCP AI client, or another plugin reproduce
   a plugin conflict for a browser session or a support call, then restore the site
   to its exact prior state by clearing one JSON file. Overrides cascade through
   WP 6.5+ `Requires Plugins:` headers by default. Every `active=true` write is 
   guarded by a WordPress-core-style `plugin_sandbox_scrape` probe, so a broken 
   plugin can never leave the site in a state where every subsequent page load fatals—
   the override is refused instead. Feature 061.

All overrides are stored in a dedicated database table. The WordPress ability registry
is never modified — only the fields that differ from registry defaults are persisted.

**Security:**

 * All endpoints require `manage_options` capability.
 * All state-changing requests are protected by WordPress nonce verification.
 * All input is sanitized; all output is escaped.

**Third-party integrations (optional):**

 * **MCP Adapter plugin** — if active, the plugin displays a list of registered 
   MCP servers inside the ability edit panel. No data is sent to any external service.
   The MCP Adapter plugin communicates only with your own WordPress installation.

This plugin's own code makes no external HTTP requests. One admin-only surface can
contact an external service on your behalf: the AcrossAI  Add-ons page installs 
WordPress.org-hosted companion plugins directly through WordPress core's own plugin
installer (`api.wordpress.org` + `downloads.wordpress.org`). Add-ons registered 
with any other source (e.g. GitHub, Freemius) are shown as external “Get add-on ”
links that open the vendor's site in a new browser tab — the plugin does not download
or install them itself. The AcrossAI  Consultations submenu renders a static call-
to-action button that opens `calendly.com` in a new browser tab only after the administrator
clicks it — no third-party asset is loaded inside wp-admin. Full disclosure — including
what data is transmitted to each service and links to their terms + privacy policies—
is in the **External Services** section below.

### External Services

This plugin connects to the following external services on your behalf. Each connection
is triggered by a specific admin-only action and is disclosed here per the WordPress.
org plugin directory guidelines.

**1. Calendly external link (`calendly.com`)**

_What it is:_ Calendly is a third-party scheduling service. The AcrossAI  Consultations
submenu displays a static call-to-action button that links out to a Calendly booking
page for AcrossAI consultations (“Using AI in WordPress”).

_When it is contacted:_ Never on page render. The Consultations submenu at `/wp-
admin/admin.php?page=acrossai-consultations` is a self-contained wp-admin page —
it does not load any Calendly script, iframe, cookie, or asset. Calendly is only
contacted if the administrator explicitly clicks the “Book a Consultation” button,
at which point their browser navigates directly to `https://calendly.com/acrossai/
using-ai-in-wordpress` in a new tab (`target="_blank" rel="noopener noreferrer"`).
This is identical to clicking any external hyperlink from an admin page.

_What is loaded on the Consultations page:_ Nothing from Calendly. The page renders
self-contained HTML + CSS. The only external asset referenced by the page is Google
Fonts (Space Grotesk + IBM Plex Sans via `fonts.googleapis.com`) — permitted under
the “third-party CDNs beyond fonts” carve-out in the WordPress plugin guidelines.

_What data is transmitted to Calendly:_ Nothing by this plugin. If the administrator
clicks the CTA button, their browser navigates directly to Calendly and sends standard
browser metadata (IP address, User-Agent, referrer) to Calendly as with any external
link. If the administrator then chooses to book a consultation on Calendly's own
site, any information they enter into Calendly's booking form (name, email address,
meeting preferences, etc.) is transmitted to and processed by Calendly. This plugin
does not intercept, store, or forward that data.

_Terms of service:_ https://calendly.com/pages/terms
 _Privacy policy:_ https://
calendly.com/pages/privacy

**2. WordPress.org plugin directory (`api.wordpress.org` and `downloads.wordpress.
org`)**

_What it is:_ The Add-ons page (`/wp-admin/admin.php?page=acrossai-addons`) uses
the WordPress.org plugin directory to install free companion plugins directly from
wp-admin.

_When it is contacted:_ Only when an authenticated administrator (`install_plugins`
capability) clicks the “Install” button on a card whose `source` is `wordpress.org`.
Contact happens through WordPress core's own `plugins_api()` and `Plugin_Upgrader`—
this plugin does not issue direct HTTP requests. Add-ons registered with any other
source (e.g. `github`, `freemius`) are rendered as external “Get add-on ” links 
that open the vendor's site in a new browser tab; the plugin does NOT download or
install those add-ons itself, so no request is made to the vendor's servers from
wp-admin.

_What data is transmitted:_ The WordPress core plugin API request payload (site 
URL, WP version, PHP version, locale) as per WordPress core's standard update check
protocol.

_Terms of service:_ https://wordpress.org/about/terms/
 _Privacy policy:_ https://
wordpress.org/about/privacy/

**3. WordPress.org core version-check API (`api.wordpress.org/core/version-check/
1.7/`)**

Called only when an administrator invokes the `core/rollback-wp-core` ability (registered
under the Core category) and the local core-version cache has expired. Rate-bounded
to at most one request per day per locale per site via a site-transient cache. This
is a WordPress-core-hosted API — no data beyond the standard WordPress core version-
check request payload is transmitted. Same wp.org terms + privacy policy as service#
2 above.

### Privacy Policy

This plugin does not itself collect, store, or transmit any user data to any third
party.

Several admin-only actions can cause external services to receive data — all are
described in the External Services section above and are triggered only by an authenticated
administrator:

 * The AcrossAI  Consultations admin page displays a static call-to-action button.
   Merely loading the Consultations page sends no data to Calendly — no Calendly
   script, iframe, or asset is loaded inside wp-admin. If the administrator clicks
   the CTA button, their browser opens `calendly.com/acrossai/using-ai-in-wordpress`
   in a new tab, at which point standard browser metadata (IP, User-Agent, referrer)
   is sent to Calendly and Calendly's own privacy policy applies. If they then book
   a consultation on Calendly's site, information they enter into Calendly's form(
   name, email, meeting details) is transmitted to Calendly.
 * Installing a WordPress.org-hosted add-on from the AcrossAI  Add-ons page contacts
   the WordPress.org plugin directory via WordPress core's own `plugins_api()` and`
   Plugin_Upgrader` (`api.wordpress.org` + `downloads.wordpress.org`). Add-ons distributed
   elsewhere (e.g. GitHub, Freemius) are rendered as external “Get add-on ” links
   that open the vendor's site in a new browser tab — the plugin itself does not
   download or install those add-ons, so no request is sent to the vendor's servers
   from wp-admin. If the administrator clicks the external link, their browser navigates
   directly to the vendor and standard browser metadata (IP, User-Agent, referrer)
   is sent to the vendor as with any external hyperlink.
 * Invoking the `core/rollback-wp-core` ability contacts the WordPress.org core 
   version-check API (a WordPress-core-hosted service) via the standard WordPress
   update API.

No data is sent to any external server without an explicit administrator action.

## Slike ekrana

[⌊The Abilities Manager admin page — searchable, sortable ability table.⌉⌊The Abilities
Manager admin page — searchable, sortable ability table.⌉[

The Abilities Manager admin page — searchable, sortable ability table.

[⌊The edit drawer — tri-state override controls for each ability field.⌉⌊The edit
drawer — tri-state override controls for each ability field.⌉[

The edit drawer — tri-state override controls for each ability field.

[⌊Bulk actions toolbar for allow/disallow/reset across multiple abilities.⌉⌊Bulk
actions toolbar for allow/disallow/reset across multiple abilities.⌉[

Bulk actions toolbar for allow/disallow/reset across multiple abilities.

[⌊The Ability Library page — enable/disable add-on ability groups.⌉⌊The Ability 
Library page — enable/disable add-on ability groups.⌉[

The Ability Library page — enable/disable add-on ability groups.

[⌊The Add-ons page — browse free companion plugins.⌉⌊The Add-ons page — browse free
companion plugins.⌉[

The Add-ons page — browse free companion plugins.

[⌊Settings — Display (abilities-per-page) and Upload Media Abilities (allowed-MIME
list + Add file types).⌉⌊Settings — Display (abilities-per-page) and Upload Media
Abilities (allowed-MIME list + Add file types).⌉[

Settings — Display (abilities-per-page) and Upload Media Abilities (allowed-MIME
list + Add file types).

## Instalacija

 1. Upload the `acrossai-abilities-manager` folder to `/wp-content/plugins/`.
 2. Activate the plugin through the **Plugins** menu in WordPress.
 3. Navigate to **AcrossAI Abilities Manager** in the WordPress admin menu.

**Add-ons:**

 1. Go to **AcrossAI  Add-ons** to browse available companion plugins.
 2. All add-ons are free and hosted on WordPress.org; each card offers a one-click 
    Install / Activate / Deactivate action via the standard WordPress plugin installer.

## ČPP

### Does this plugin support Multisite?

No. This plugin has not been tested on WordPress Multisite installations.

### Does this plugin modify the WordPress ability registry?

No. The plugin stores only overrides — fields that differ from the registry defaults.
The ability registry itself (`wp_get_ability()`) is never modified.

### What happens when I reset an override?

The override row is deleted from the database. The ability will inherit its values
from the registry again.

### What is the Ability Library?

The Library page lets you enable or disable ability groups registered by add-on 
plugins. Each group shows an ON/OFF master toggle and an All/Specific mode selector.
In Specific mode, individual ability slots can be toggled independently.

### What is the MCP Adapter integration?

If the MCP Adapter plugin is active on your site, AcrossAI Abilities Manager will
display the list of registered MCP servers in the ability edit panel. This is entirely
optional — the plugin works without the MCP Adapter.

### Does this plugin make external HTTP requests?

The plugin's own code makes no external HTTP requests. Two admin-only surfaces trigger
external connections on behalf of an authenticated administrator:

 * **AcrossAI  Consultations** submenu — renders a static call-to-action button 
   that links to `https://calendly.com/acrossai/using-ai-in-wordpress` and opens
   in a new browser tab. The plugin does not load any Calendly script, iframe, or
   asset inside wp-admin. Calendly is only contacted if the administrator explicitly
   clicks the button — at which point their browser navigates directly to `calendly.
   com`, exactly as with any external hyperlink.
 * **AcrossAI  Add-ons** submenu — installs WordPress.org-hosted companion plugins
   in place through WordPress core's `plugins_api()` + `Plugin_Upgrader` (contacts`
   api.wordpress.org` + `downloads.wordpress.org`). Add-ons registered with any 
   other source (e.g. GitHub, Freemius) render as external “Get add-on ” links that
   open the vendor's site in a new browser tab — the plugin does not download or
   install those add-ons itself. Users install off-directory add-ons via WP admin's
   standard **Plugins  Add New  Upload Plugin** flow (or via the vendor's own installer
   once the paid plugin is activated).

Full disclosure — including what data is transmitted, and links to each service's
terms + privacy policy — is in the **External Services** section of this readme.

## Recenzije

Nema recenzija za ovaj dodatak.

## Saradnici i programeri

“AcrossAI Abilities Manager” is open source software. The following people have 
contributed to this plugin.

Doprinositelji

 *   [ Deepak Gupta ](https://profiles.wordpress.org/raftaar1191/)

[Prevedi “AcrossAI Abilities Manager” na vaš jezik.](https://translate.wordpress.org/projects/wp-plugins/acrossai-abilities-manager)

### Zainteresirani za razvoj?

[Pregledajte kôd](https://plugins.trac.wordpress.org/browser/acrossai-abilities-manager/),
pogledajte [SVN spremište](https://plugins.svn.wordpress.org/acrossai-abilities-manager/)
ili se pretplatite na [dnevnik razvoja](https://plugins.trac.wordpress.org/log/acrossai-abilities-manager/)
od [RSS](https://plugins.trac.wordpress.org/log/acrossai-abilities-manager/?limit=100&mode=stop_on_copy&format=rss).

## Zapis promijena

#### Unreleased

#### 0.0.33 – 2026-08-28

**Release theme: closing the cheap-edit loop.** A follow-up to 0.0.32 that closes
the last two gaps between “locate a block cheaply” and “modify it cheaply”. Two 
changes, both surgical and backwards-compatible.

**`return_content:false` default now covers the two block-tree writers.** `blocks/
add-block` and `blocks/update-post-block` gain the same `return_content:{boolean,
default:false}` input as the six content writers (PR #152) and nine block-editor
writers (PR #153). When false (default), the response's `block` object strips its`
innerHTML`, `innerContent`, and `innerBlocks` — leaving `blockName`, `attrs`, and`
path` — and `content_bytes` reports the saved `innerHTML` size. Container blocks(
columns, cover, group) previously echoed their entire innerBlocks subtree; now they
don't unless the caller passes `return_content:true`. BREAKING for callers reading`
response.block.innerHTML` on these two abilities — pass `return_content:true` explicitly.
Every other block-tree read/write (mutate-block-tree, replace-block-text, remove-
block, duplicate-block, move-block) already returned lightweight envelopes and is
unchanged.

**`blocks/get-post-blocks` gains scoping inputs.** Three new optional inputs close
the “read one block's markup” gap between `blocks/get-post-blocks` (full tree, full
content) and `blocks/outline-post-blocks` (scoped but never returns content). `path:
int[]` scopes the response to a subtree (uses the same raw parse_blocks() index 
scheme as add-block / update-post-block / remove-block, so returned paths interchange).`
depth: integer` bounds descent below the subtree root (-1 unlimited, 0 subtree root
only, N below). `include_html: boolean` (default true = backwards-compat) strips
innerHTML + innerContent from every returned node when false. Backwards-compatible:
existing callers passing only `post_id` see identical responses. An unresolvable`
path` returns a standard error envelope with `error_code: invalid_path` naming which
depth failed and how many blocks exist at that level.

#### 0.0.32 – 2026-08-28

**Release theme: token-efficient AI callers.** Two closely related shifts. First,
response payloads shrink dramatically for the common “small edit” and “just tell
me the block structure” intents. Second, ability descriptions gain author-declared
hints pointing AI callers at cheaper sibling abilities when their intent maps to
one. Every change is either strictly additive or opt-out only via an admin toggle—
no ability's execute() behaviour changes.

**Token-efficiency default for six content writers.** `content/create-page`, `content/
update-page`, `content/create-post`, `content/update-post`, `content/create-cpt-
item`, `content/update-cpt-item` gain a new optional input `return_content:boolean,
default:false`. When false (the default), the response's `page` / `post` / `item`
object strips three large fields — `post_content`, `post_content_filtered`, `post_excerpt`—
and adds `content_bytes:integer` so callers still see the saved payload size at 
a glance.

**Why.** A single-word edit on a ~97 KB page via `content/update-page` previously
round-tripped ~60 K LLM tokens (the caller sent the whole new body and the ability
echoed the same body back). With this default, the echo drops to ~0 tokens — the
caller pays only for the upload it already had to make. Fine-grained edits via `
blocks/update-post-block` remain ~10× cheaper still because they never touch the
surrounding content.

**BREAKING for callers reading `response.page.post_content` (or `.post` / `.item`
equivalents).** Existing callers that need the saved content back — e.g. to diff
against what they sent — must pass `return_content:true` explicitly. The three stripped
fields remain queryable via `content/get-page` / `content/get-post` after the write.

**Not affected.** Every other content ability (get / list / delete / block-tree 
operations / meta ops) is unchanged. The block-tree writers (`blocks/update-post-
block`, `blocks/add-block`, etc.) already returned just the modified block, not 
the whole page — nothing to strip.

**Same default now applies to nine block-editor writers.** `blocks/create-block-
pattern`, `blocks/create-block-template`, `blocks/update-block-template`, `blocks/
create-block-template-part`, `blocks/update-block-template-part`, `blocks/create-
block-style-variation`, `blocks/update-block-style-variation`, `blocks/create-global-
style`, and `blocks/update-global-style` gain the same `return_content:boolean, 
default:false` input. Response objects (`pattern` / `template` / `part` / `variation`/`
record`) strip the large `content` (pattern/template/template-part markup) or `data`(
variation/theme.json JSON) field by default and add `content_bytes:integer`. For`
Variation_Db::to_row` and `Global_Styles_Db::to_row`, the writers now pass the caller's`
$return_content` through instead of hardcoding `true` — the helpers skip `decode_content()`
when the payload isn't wanted (CPU saving on the hot path). BREAKING for callers
reading `response.pattern.content`, `response.template.content`, `response.part.
content`, `response.variation.data`, or `response.record.data` — pass `return_content:
true` explicitly. `blocks/update-block-pattern` is unchanged — it already returned
a lightweight location descriptor.

**New ability `blocks/outline-post-blocks`.** Returns a flat, depth-first index 
of a post's block tree — canonical path, block type, child count, byte size, and
a short text preview — without any block content. Cheap way for an LLM caller to
locate a block before editing it: `blocks/get-post-blocks` on a large page can be
hundreds of kilobytes because it returns every block's full `innerHTML`; this ability
returns kilobytes for the same post. Paths use the same raw-`parse_blocks()` index
scheme as `Block_Tree`, so a path returned here is drop-in usable with `blocks/add-
block`, `blocks/update-post-block`, and `blocks/remove-block`. Paths are positional—
a write can re-serialize the post and shift raw indices — so the response includes`
post_modified_gmt` for staleness detection; re-outline after each write rather than
caching paths. Filters (`block_names`, `contains`, `max_text`, `depth`, `include_attrs`,`
max_results`) compose. `contains` matches only within the extracted text preview(
up to `max_text` characters); raise `max_text` for deeper substring searches. Whitespace
nodes (`parse_blocks` entries with null `blockName`) are excluded from output but
still consume index positions — same convention `Block_Tree` already uses. `readonly`,`
idempotent`, `non-destructive`.

**New — Ability Suggestions framework (Feature 095).** Ability authors can now declare
a small list of other abilities an AI caller might use instead — a token-saving 
hint mechanism mirroring Feature 088's `suggested_plugins()`. Each ability class
can override a new protected method `suggested_abilities()` returning `array<int,
array{slug: string, reason: string, saves?: string}>`; entries surface under `args.
meta.acrossai.suggested_abilities` on `mcp-adapter-get-ability-info` (not on discover-
abilities — details-only surface, avoids discovery bloat). Hints are strictly advisory—
nothing about the original ability's execution changes. Four initial ability overrides
ship in this release: `content/update-page`, `content/update-post`, `content/update-
cpt-item` each suggest `blocks/outline-post-blocks` + `blocks/update-post-block`
for narrow edits (~29K tokens saved on a 97 KB page); `blocks/get-post-blocks` suggests`
blocks/outline-post-blocks` when only paths are needed (~28K tokens saved on the
same page). New admin toggle “Disable ability suggestions” on the Abilities settings
tab (between “Plugin Suggestions” and “Uninstall Settings”) strips the field site-
wide (option key `acrossai_disable_ability_suggestions`, default `0` = feature enabled).
Uninstall cleans up the option when “delete all data” is on. An ability with no 
override produces a byte-identical payload to what it produced before Feature 095—
no schema drift, no phantom empty list.

**Ten more `suggested_abilities()` overrides added to the Feature 095 hint catalog.**`
content/get-page`, `content/get-post`, `content/get-cpt-item` each hint that `blocks/
outline-post-blocks` is far cheaper (~20×) when the caller only needs to locate 
a block or see the structure. `blocks/read-theme-json` hints that `blocks/get-style-
guide` returns a normalized token summary (~5–8×) when the caller wants design tokens,
not the raw spec. `options/list-options`, `media/list-media`, `users/list-users`,`
blocks/list-block-templates`, `blocks/list-block-patterns`, `blocks/list-global-
styles` each hint that their corresponding targeted-read siblings (`options/get-
option`, `media/get-media`, `users/get-user`, `blocks/read-block-template`, `blocks/
read-block-pattern`, `blocks/read-global-style`) are 5–30× cheaper when the caller
already knows the identifier — list is for discovery, get/read is for retrieval.

#### 0.0.31 – 2026-08-26

**Release theme: File Manager consolidation + hardening + audit log.** Bundles the
six-feature series (089  094) that turned `file-manager/*` from a loose collection
of read/write primitives into a self-contained subsystem with an admin tab, allowlist-
and-content-filter enforcement, and an append-only audit log with pre-image backups.
Also cuts the inline `.bak.<timestamp>` scheme in `Delete_File` (BREAKING for callers
of `response.backup` — new canonical field is `response.backup_path`).

**Feature 094 — File Manager Audit Log + Backup Harness (partial).** Consumes the
four Backup & Audit option keys shipped as scaffold in PR #144 and enforced-toggle-
only in PR #146. New `Audit_Trail` utility owns pre-image backups (into `wp-content/
acrossai-file-manager-backups/<YYYY-MM-DD>/`) + append-only log (into `wp-content/
acrossai-file-manager-logs/acrossai-file-manager.log`) + amortised 1-in-10 cleanup
+ stats. Both storage locations get a `Deny from all` `.htaccess` on first creation.
All I/O goes through `WP_Filesystem`.

**New ability:** `file-manager/get-changelog` — tails the last N entries (default
100, max 500) via MCP. Honours the read allowlist. Empty log returns a friendly 
message, not an error. `manage_options` gated.

**Log entry format** (blank-line separated, one entry per mutation):

[YYYY-MM-DD HH:MM:SS UTC]
 Ability: file-manager/ File: User: (ID:) IP: Size: ->
bytes Destination: (COPY / MOVE only) Backup: Context:

**New action hook:** `do_action('acrossai_file_manager_log_entry', $entry)` fires
after every log write. Subscribers (Slack, Datadog, SIEM…) receive the parsed entry
as an assoc array. Zero cost when no subscribers.

**New optional `context` input field** on wired abilities (`delete-file`, `edit-
file`, `create-directory` in this PR — more in the follow-up). Schema max 2000 chars;
log writer truncates to 500 chars via `sanitize_text_field` before persisting.

**BREAKING — `file-manager/delete-file` `backup` response field.** The inline `<
path>.bak.<time>` scheme is REPLACED by the centralised backup dir. When `backup_enabled
=true` the response's new canonical field is `backup_path`; the legacy `backup` 
field is populated with the same value for one transition release and will be removed.
When `backup_enabled=false` NO backup is written at all — callers who relied on 
the inline `.bak` return value now get `null` for both fields when the toggle is
off. Direct callers to read `backup_path` instead of `backup`.

**Retention.** `backup_retention_days` deletes backup dirs older than N days; `audit_log_retention_days`
trims log entries older than N days. Both fire probabilistically (1-in-10 per log
write) — no WP-Cron dependency.

**Scope note (PARTIAL).** This PR wires three abilities end-to-end (`delete-file`,`
edit-file`, `create-directory`) to prove the design across the backup + log-only
paths. The remaining seven mutation abilities (`create-file`, `append-file`, `copy-
file`, `move-file`, `delete-directory`, `edit-wp-config`, `clear-debug-log`) and
the `BackupAuditPanel` scaffold-banner flip + `/backup-audit-stats` REST endpoint
+ uninstall extension are DEFERRED to a follow-up PR. Test coverage is scoped accordingly(
35 new tests, mostly structural — behavioural I/O tests need a full-WP bootstrap
and run in the CI matrix).

**Feature 093 — File Manager Hardening (enforcement pass for PR #144 scaffold).**
The eight Content Filters knobs and the one sensitive-read denylist that PR #144
shipped as UI scaffold are now enforced at runtime by every file-manager write ability
and by `file-manager/read-file`. Persistence layer (`Hardening_Settings`) unchanged;
the new `Hardening_Enforcer` utility runs each check after the existing `File_Mods_Guard`
+ `Path_Allowlist_Guard` gates and returns the standard `{success:false, blocked_reason,
path, message, …context}` envelope on refusal. Enforcement order (best-cheap-first):
dangerous_extensions  block_double_extensions  sanitize_filename_check  strict_filename_filter
mime_type_check  htaccess_directive_scan  write_max_bytes. Empty list / false toggle
is a no-op so callers upgrading with defaults get zero behaviour change beyond what
defaults dictate.

**Six abilities wired** — `file-manager/{create-file, edit-file, append-file, copy-
file, move-file}` for the seven content-filter checks; `file-manager/read-file` 
for the sensitive-read denylist. Copy/move check the DESTINATION basename; append-
file scans only the appended bytes for `.htaccess` directives and caps size on `
new_size = existing + appended`; copy/move use source file size for the size cap
and read source content lazily for the `.htaccess` scan (only when destination basename
is `.htaccess`). `mime_type_check` skips append-file (extension didn't change) and
always allows `{php, txt, log, json, xml, css, js, md, html, htm, htaccess}` even
with the check on — prevents breaking the mu-plugins deploy use case the write allowlist
explicitly permits.

**Eight new `blocked_reason` values** — `extension_blocked` (+`extension`), `double_extension_blocked`(
+`basename`), `htaccess_directive_blocked` (+`directive`), `filename_sanitize_failed`(
+`input`, `sanitized`), `write_size_exceeded` (+`size`, `max_bytes`), `filename_strict_blocked`(
+`marker`), `mime_type_blocked` (+`extension`), `sensitive_read_blocked` (+`basename`,`
matched_pattern`). Every affected ability's `output_schema` declares the union of
these context fields. Existing `path_not_allowed_for_write` / `path_not_allowed_for_read`/`
protected_write` / `file_mods_disabled` envelopes are unchanged and take precedence—
hardening refusals fire only when all earlier gates pass.

**Ordering guarantee** — sensitive-read denylist runs AFTER the read allowlist (
spec FR-011). If the allowlist would refuse a path, that refusal (`path_not_allowed_for_read`)
is returned; the denylist only fires when the allowlist would permit. This lets 
an admin safely widen the read allowlist and still keep `.env / *.key / id_rsa` 
blocked.

**Panel banner update** — the Content Filters panel drops its yellow “Scaffold only”`
notice-warning` (added in PR #144) and replaces it with a small `notice-info` reading“
This list now gates create-file / edit-file / append-file / copy-file / move-file.”
The Backup & Audit panel keeps its scaffold banner but the text now references `
094-file-manager-audit-log` explicitly. REST GET `/acrossai/v1/file-manager-settings/
content-filters` flips `scaffold_only:true → false` and `follow_up_spec` becomes`
null`; `/backup-audit` unchanged.

**Dotfile carve-out for `sanitize_filename_check`.** Legitimate WordPress-adjacent
dotfiles (`.htaccess`, `.htpasswd`, `.user.ini`) are exempted from the sanitize-
filename roundtrip check because real WP's `sanitize_file_name()` strips leading
dots — applied literally, the check would refuse every valid dotfile and starve 
the htaccess-directive scanner of any target. Other dotfiles (`.gitignore`, `.env`,
etc.) are still refused when the check is on; admins who need them disable the check.

**Not touched.** `Delete_File`, `Delete_Directory`, `Create_Directory`, `File_Info`,`
Read_Debug_Log` (fixed target), `Read_Wp_Config`, `Get_Wp_Config_Constant`, `Edit_Wp_Config`,
all six zip abilities — spec explicitly excludes these.

**Feature 092 — File Manager admin tab: per-folder read/write allowlists + configurable
secret redactor.** New “File Manager” tab at `admin.php?page=acrossai-settings` 
gives site admins three per-folder controls over what MCP clients can do via `file-
manager/*` abilities. Also introduces a hardened secret-scrubber that runs on every
read response.

**Write allowlist.** The 8 write-capable file-manager abilities (`create-file`, `
edit-file`, `delete-file`, `copy-file`, `move-file`, `append-file`, `create-directory`,`
delete-directory`) refuse any operation whose target path resolves outside the admin's
allowlist. Default on activation: `['wp-content']` (writes only inside wp-content).`
copy-file` and `move-file` check both source and destination. Refusal returns `{
success:false, blocked_reason:"path_not_allowed_for_write", allowed_roots:[…]}`.

**Read allowlist.** The 2 content-reading abilities (`read-file`, `read-debug-log`)
can also be gated. Default on activation: `[]` — unrestricted (every path readable).
Admins can flip a “Restrict reads to specific folders” toggle and pick specific 
folders. Refusal returns `{success:false, blocked_reason:"path_not_allowed_for_read"}`.`
list-directory` and `file-info` remain ungated (metadata only, no content leak).

**Secret redactor.** Every text response from `read-file` and `read-debug-log` is
scrubbed before return. Ships one built-in pattern: **WordPress credentials** (DB_PASSWORD,
DB_USER, all 8 auth keys/salts, SECRET_KEY) — value replaced but constant name preserved.
Everything else the admin adds via the custom-literals textarea (case-sensitive 
string match). Third-party API-key regexes are intentionally NOT hardcoded — assumptions
about someone else's key format belong in the site's own config, not in this plugin.

**Auto-scrub for AI-connector API keys.** If the WordPress **AI plugin** (github.
com/WordPress/ai) is installed and any of its provider connectors has an API key
configured, that value is added to the redactor's literal list transparently — the
admin does not have to copy those keys into the custom-literals textarea. Currently
covers OpenAI (`connectors_ai_openai_api_key`), Anthropic (`connectors_ai_anthropic_api_key`),
and Google (`connectors_ai_google_api_key`). No configuration required; the redactor
reads these options on every scrub call. Responses grow two fields: `redacted:bool`
and `redaction_count:int`.

**REST endpoints.** Six new routes under `acrossai/v1`: GET/POST `/file-manager-
settings/write-allowlist`, `/read-allowlist`, `/redaction`. `manage_options` + `
X-WP-Nonce` required. GET responses include enumeration data (immediate ABSPATH 
children, `get_plugins()`, `wp_get_themes()`) so the React UI renders without a 
second round-trip.

**BREAKING — `file-manager/read-file`.** The previous outright refusal of `wp-config.
php` and `.htaccess` (`blocked_reason:"protected_read"`) is REMOVED. Those files
are now readable; sensitive content is redacted per the secret redactor above. Callers
that programmatically handled `blocked_reason:"protected_read"` should switch to
reading the returned content with `redacted:true`. Write-side refusals on `wp-config.
php` / `.htaccess` for `create-file`, `edit-file`, `delete-file`, `copy-file`, `
move-file`, `append-file` are UNCHANGED.

**Not touched.** `Ability_Definition`, `File_Mods_Guard`, `Wp_Filesystem_Init`, `
read-wp-config`, `edit-wp-config`, `get-wp-config-constant`, `list-directory`, `
file-info`, all 6 zip-backup abilities, and every ability outside `file-manager/*`.

#### Feature 091 milestone

**Feature 091 — WP_Filesystem migration for `file-manager/\*` abilities.** Every
filesystem read, write, list, delete, copy, move, and stat performed by 19 file-
manager abilities now routes through WordPress's `WP_Filesystem` transport instead
of raw PHP filesystem functions. On the majority of hosts (`FS_METHOD='direct'`)
the behaviour is identical. On hosts where WordPress requires FTP / SSH credentials(`
FS_METHOD='ftpext'` / `'ftpsockets'` / `'ssh2'`) the abilities now succeed via the
same channel WordPress core's file editor uses instead of silently failing.

**Biggest wins — `wp-config.php` and `debug.log`:** `file-manager/read-wp-config`,`
file-manager/edit-wp-config`, `file-manager/read-debug-log`, `file-manager/clear-
debug-log` are the abilities most likely to touch files owned by the SSH user rather
than the web-server user. Those calls previously failed on non-`direct` transports;
they now work.

**New response value:** every migrated ability's `blocked_reason` enum widens by
one value — `filesystem_unavailable` — returned when `WP_Filesystem()` initialisation
fails (typically missing `FTP_HOST` / `FTP_USER` / `FTP_PASS` on a non-`direct` 
host).

**BREAKING — `file-manager/file-info` schema shrink:** the response no longer includes`
ctime` or `atime` fields. `WP_Filesystem_Base` does not expose these consistently
across transports (native `stat` returns them on `direct`, FTP/SSH transports don't).
Callers programmatically reading `.ctime` or `.atime` must switch to `.mtime` or
accept the loss. Every other field on the response is unchanged.

**Deferred to feature 092:** `file-manager/create-zip-backup`, `file-manager/extract-
zip-backup`, and `file-manager/upload-zip-backup` remain on native PHP for now. `
ZipArchive` requires direct filesystem access and has no `WP_Filesystem` equivalent,
and chunked upload uses `fopen`/`fwrite`/`fclose` file-handle APIs that `WP_Filesystem`
does not expose. These three abilities continue to work exactly as before on `direct`
transports and continue to fail as before on FTP/SSH ones. Every file carries a `//
TODO(feature-092)` marker.

**Housekeeping:** approximately 20 `phpcs:ignore WordPress.WP.AlternativeFunctions`
suppressions removed from the 19 migrated files. `Ability_Definition` and `File_Mods_Guard`
are unchanged (verified — sibling plugin `acrossai-buddyboss` continues to extend
the former without issue).

**Feature 090 — file-manager additions.** Four new abilities extend the `file-manager/*`
namespace to cover directory management and metadata: `file-manager/append-file`(
append or prepend to an existing file; refuses missing files and refuses `wp-config.
php` / `.htaccess`), `file-manager/create-directory` (recursive-by-default `mkdir`
under ABSPATH; idempotent), `file-manager/delete-directory` (empty-only by default;
opt-in `recursive:true`; requires `confirm:true`; refuses nine critical WordPress
directories), and `file-manager/file-info` (read-only stat wrapper with optional
POSIX owner/group names). Ability count 385  389.

**Feature 089 — file abilities consolidation.** Every file read / write / list /
copy / move for the WordPress installation now flows through the `file-manager/*`
namespace. Three new abilities added; six duplicate theme- and plugin-scoped abilities
removed; a pre-existing security gap closed.

**Added — three new `file-manager/\*` abilities:**

 * **`file-manager/list-directory`** — recursive directory walk under ABSPATH. Bounded
   by `max_depth` (default 5, max 20) and `max_entries` (default 1000, max 5000);
   response sets `truncated:true` when a bound is reached. Symlinks are not followed.
   Replaces `themes/read-theme-structure` and `plugins/read-plugin-structure`.
 * **`file-manager/copy-file`** — copy a file between two paths under ABSPATH. Default
   refuses when the destination exists; pass `overwrite:true` to replace. Refuses
   copies **onto** `wp-config.php` or `.htaccess` even with `overwrite:true`. Replaces
   the copy mode of `plugins/manage-plugin-files`.
 * **`file-manager/move-file`** — rename/move a file between two paths under ABSPATH.
   Same overwrite semantics as `copy-file`, plus refuses moves **from** `wp-config.
   php` or `.htaccess`. Replaces the move mode of `plugins/manage-plugin-files`.

**Removed — six duplicate abilities (BREAKING):** any MCP client hardcoding these
slugs will get an “unknown ability” error. Migrate to the `file-manager/*` replacement.

 Removed slug
 Replacement

 `themes/read-theme-code`
 `file-manager/read-file`

 `themes/edit-theme-file`
 `file-manager/edit-file`

 `themes/read-theme-structure`
 `file-manager/list-directory`

 `plugins/read-plugin-code`
 `file-manager/read-file`

 `plugins/read-plugin-structure`
 `file-manager/list-directory`

 `plugins/manage-plugin-files`
 `file-manager/copy-file` or `file-manager/move-file`

**Hardened — `file-manager/create-file` and `file-manager/edit-file` now refuse `
wp-config.php` and `.htaccess`.** Before this release, these two abilities silently
allowed overwriting those files even though `read-file` and `delete-file` refused
them. This closes the last generic write path to those protected files; the specialized`
file-manager/edit-wp-config` (single-constant edit with secret-key allowlist) remains
the only supported way to modify `wp-config.php`.

**Kept as-is (not duplicates):** `file-manager/read-wp-config`, `file-manager/edit-
wp-config`, `file-manager/get-wp-config-constant`, `file-manager/read-debug-log`,`
file-manager/clear-debug-log`, `recovery/list-recent-fatal-errors`, and all theme/
plugin lifecycle abilities (install / activate / update / delete-theme / lifecycle-
context / checksums / etc.).

**Ability count:** 388  385 (-6 removed, +3 added). Full per-ability inventory refreshed
at `docs/abilities-inventory.md`.

#### 0.0.30 – 2026-08-19

**Ability namespace migration — every ability slug moves from `acrossai/\*` to a
topic-based prefix.** 388 abilities across 24 topic namespaces. No behavioural changes;
this is a slug rename only. Delivered as four disjoint PRs merged in order: #134(
blocks), #135 (elementor), #136 (rank-math), #137 (remaining 21 domains).

**Breaking for every MCP client:** any reference to `acrossai/<slug>` must switch
to `<topic>/<slug>`. There is no back-compat alias — discovery now returns the new
names only.

 * **`blocks/\*` (40)** — every block-editor primitive: templates, template parts,
   patterns, style variations, global styles, theme.json, site-editor context, blocks/
   reusable blocks. Also includes the 7 block-tree ops that previously lived under`
   acrossai/*` in the Content folder (add-block, duplicate-block, get-post-blocks,
   insert-pattern, move-block, remove-block, update-post-block). Prefix-only rename—
   the second segment is preserved (e.g. `acrossai/create-block-template`  `blocks/
   create-block-template`).
 * **`elementor/\*` (62)** — every Elementor ability. Redundant `elementor-` fragment
   collapsed into the namespace, so `acrossai/elementor-add-widget`  `elementor/
   add-widget`, `acrossai/elementor-create-template`  `elementor/create-template`,
   etc. `Base_Audit_Ability` now builds slugs as `'elementor/' . audit_slug()` —
   all dynamic audit subclasses inherit the new prefix.
 * **`rank-math/\*` (61)** — every Rank Math ability. Redundant `rank-math-` fragment
   collapsed. `Base_Rank_Math_Ability` slug construction changed in one line (`'
   rank-math/' . slug()`) — the entire suite picks up the rename automatically. 
   User-visible error messages that name specific slugs (e.g. `Utilities/RankMath/
   Maintenance_Tools`) refreshed to match.
 * **Remaining 21 topic namespaces (225)** — prefix-only rename per domain:
    - `admin-menu/` (5), `cache/` (7), `comments/` (12), `content/` (29), `content-
      search/` (11), `core/` (6), `cron/` (16), `database/` (11), `file-manager/`(
      15), `fonts/` (8), `media/` (11), `menus/` (12), `options/` (7), `plugins/`(
      13), `recovery/` (7), `settings/` (11), `site-health/` (6), `taxonomies/` (
      10), `themes/` (10), `users/` (16), `widgets/` (2).
    - Examples: `acrossai/get-option`  `options/get-option`; `acrossai/list-db-tables``
      database/list-db-tables`; `acrossai/create-user`  `users/create-user`.
    - The second segment is unchanged from what shipped before — only the vendor
      prefix moves. No collapsing (unlike Elementor/Rank Math, where the redundant
      fragment was literally the namespace name).

**Why:** topic namespaces make the ability surface discoverable — a client fetching`
mcp-adapter-discover-abilities` and filtering on the prefix gets exactly the domain
it asked for. The old `acrossai/` prefix tagged ownership but carried no discovery
information. Full per-ability inventory is now published at `docs/abilities-inventory.
md`.

**Category taxonomy slugs (`acrossai-abilities-manager-\*`) are unchanged.** Internal
PHP class namespaces are unchanged. Tests, spec artifacts, and docstring cross-references
were updated in the same commits as the slug renames — nothing left pointing at `
acrossai/*`.

#### 0.0.29 – 2026-08-18

**Feature 065 — safety envelope + payload enrichment across 9 existing abilities.**
No new abilities. Plugin version bumped 0.0.28  0.0.29. Two changes are breaking
for programmatic callers: `media/delete-media` and `file-manager/delete-file` now
require an explicit `confirm: true`; `content/update-post` silently strips protected
meta keys (reported back in `dropped_meta_keys`). Every guardrail-triggered refusal
now returns `success: false` + a machine-readable `blocked_reason` + a human `message`,
with no state mutation on the refusal path.

 * **`plugins/deactivate-plugin` — protected-plugin guard.** Refuses to deactivate`
   acrossai-mcp-manager`, `acrossai-abilities-manager`, or `acrossai-pro` — the 
   three plugins that host either the ability surface itself or the MCP transport
   the AI is using to reach the site. Match runs against the _resolved_ plugin file
   path, so slug / partial-name / file-path variants that fuzzy-resolve to a protected
   plugin are all refused (`blocked_reason: "protected_plugin"`).
 * **`media/delete-media` — explicit confirmation + trash-aware.** Requires `confirm:
   true` (refuses with `blocked_reason: "confirmation_required"` otherwise). Honours
   the `MEDIA_TRASH` constant — trashes when defined truthy and `force` is absent;
   permanent-deletes otherwise. Response now carries `deleted: "deleted" | "trashed"`.
 * **`file-manager/delete-file` — confirmation + protected-write + backup + opcache
   invalidation.** Requires `confirm: true`. Refuses on `wp-config.php` / `.htaccess`
   at ABSPATH (`blocked_reason: "protected_write"`). Writes a `.bak.<timestamp>`
   copy next to the target before the delete and returns the backup path in `backup`.
   Calls `opcache_invalidate()` on the deleted path when OPcache is loaded.
 * **`file-manager/read-file` — protected-read + size cap + binary detection.** 
   Refuses on `wp-config.php` / `.htaccess` at ABSPATH (`blocked_reason: "protected_read"`)—
   this closes the highest-value accidental disclosure path (database password +
   eight auth constants). Refuses files over 5 MB without loading them into memory(`
   blocked_reason: "file_too_large"`; response reports observed size + cap). Non-
   UTF-8 payloads return `{ binary: true, size, path, message }` instead of raw 
   bytes.
 * **`media/list-media` — alt-text search.** `search` now matches against `_wp_attachment_image_alt`
   postmeta in addition to WP_Query's default `s` fields (title / caption / description).
   Results are de-duplicated by attachment ID, so an image matched by both title
   and alt-text appears once.
 * **`media/update-media` — updated-fields report.** Response now carries an `updated`
   array naming each field that was actually written (subset of `title` / `caption`/`
   description` / `alt_text`), in the order fields were processed. Empty array when
   no update fields were passed.
 * **`content/update-post` — writability + protected-meta + publish / author gates.**
   Refuses on post types that are neither `public: true` nor `show_in_rest: true`(
   matches WP-REST writability). Filters caller-supplied `meta` to drop `_`-prefixed
   keys and any key that `is_protected_meta()` reports; the `acrossai_allowed_protected_meta`
   filter opts specific keys back in. Dropped keys are reported in the response 
   as `dropped_meta_keys`. Refuses `status: "publish"` (or any status entering a
   public state) unless the caller holds `publish_posts` for the post type. Refuses`
   author: <different_user_id>` unless the caller holds `edit_others_posts`.
 * **`content/get-post` — hydrated payload.** Response now includes `terms` (object
   keyed by taxonomy, each entry `{ term_id, name, slug }`), `meta` (non-protected
   keys only — same allow-list filter as `update-post`), `featured_image` (`{ id,
   url, alt }` or `null`), `permalink`, `edit_link`, and `author: { id, name }`.
   Callers no longer need 4–5 follow-up hydration calls per post.
 * **`content/delete-post` — suggested-redirect hint.** When the target was `publish`
   and `force: true` is passed, the response includes `suggested_redirect: { from:
   <permalink>, to: <parent-or-archive-or-root-url> }`. Omitted for drafts and for
   trash operations (URL may return on restore).

**Test coverage.** `Test_Feature_065_Safety_And_Payload` — 23 source-inspection 
tests covering all 23 FRs. Full suite green; PHPCS (WPCS strict) and PHPStan level
8 clean.

#### 0.0.28 – 2026-08-17

**Feature 069 — Rank Math ability suite: 61 new abilities under a new “Rank Math”
tab.** Gated on Rank Math SEO being active; absent entirely without it. Plugin version
bumped 0.0.27  0.0.28.

Coverage baseline was deliberately narrow: Rank Math core ships **13** abilities
of its own under `rank-math/`, and only those 13 counted as existing coverage. The
third-party `mcp-abilities-rankmath` companion plugin was **not** treated as coverage—
it is not ours to maintain, its writes go through raw `update_option()` blobs that
bypass Rank Math's sanitizer, and it gates every ability on blanket `manage_options`
regardless of the Role Manager. Slugs do not collide (`rank-math/` vs `rankmath/`
vs `rank-math/`).

**Batch 1 — plumbing.** `RankMath\Category_Registrar` registers `acrossai-abilities-
manager-rank-math`, guarded on `class_exists('\RankMath\Helper')`. `Base_Rank_Math_Ability`
is the sole assembler of `ability()` and sole enforcer of the `execute()` guard 
order, which is what guarantees `tab_group => 'rank-math'` on all 61 — the Feature
078 regression class. `Rank_Math_Guard` holds every guard plus the response envelope.

**Batch 2 — typed settings (6 abilities).** `rank-math/get-settings` reads any of
20 panels with each field's type, allowed values, bounds and current value, which
makes the writers’ accepted keys discoverable at runtime. `-update-general-settings`,`-
update-title-settings` and `-update-sitemap-settings` take a section/scope enum,
replacing ~20 near-identical per-panel classes. `-update-instant-indexing-settings`
and `-update-robots-txt` are separate because the first writes a different option
and the second is conditional on state the caller cannot see. Titles & Meta templates—
the global per-post-type and per-taxonomy layer — had no read or write anywhere 
before this.

**Batch 3 — Instant Indexing, modules, sitemap, routes (10 abilities).** `-submit-
urls`, `-get-indexing-log`, `-clear-indexing-log`, `-reset-indexing-key`; `-list-
modules` and `-set-module-state`; `-get-sitemap-status`, `-list-sitemap-urls`, `-
invalidate-sitemap-cache`; `-get-llms-status` and `-refresh-llms-route`. `-set-module-
state` replicates Rank Math's own `save_module()` in full including the rewrite-
rule refresh and `rank_math/module_changed` action — omitting either leaves stale
rewrite rules, so the sitemap and llms.txt routes 404 while the module reports itself
active.

**Batch 4 — redirections, 404 logs, roles (13 abilities).** `-list-redirections`(
with the `status=trashed` filter), `-find-redirection`, `-get-redirection-stats`,`-
export-redirections`, `-create-redirection`, `-update-redirection`, `-change-redirection-
status`, `-delete-redirections`, `-delete-trashed-redirections`; `-list-404-logs`
and `-delete-404-logs`; `-get-role-capabilities` and `-reset-role-capabilities`.**`-
update-redirection` fills a real gap: nothing could previously EDIT a redirection**,
and emulating it by delete-then-recreate loses the rule's id, hit counter and creation
date. Apache/Nginx export is a port of Rank Math's private formatters, since its
own exporter reads `$_GET`, calls `check_admin_referer()`, echoes and exits.

**Batch 5 — status, maintenance, backups (8 abilities).** `-get-status` (5 panels
behind an enum), `-run-maintenance-tool` (12 tools behind an enum), `-export-settings`,`-
import-settings`, `-list-backups`, `-create-backup`, `-manage-backup`, `-detect-
seo-plugins`, plus `-get-seo-analysis-results` for the cached audit.

**Batch 6 — analytics and post-level content (16 abilities).** `-get-analytics-summary`(
6 reports), `-get-analytics-rows` (3 datasets), `-get-index-status`, `-inspect-url`;`-
update-seo-meta`, `-bulk-update-meta`, `-update-seo-scores`, `-get-primary-term`,`-
update-primary-term`, `-update-post-schemas`, `-delete-post-schemas`, `-get-schema-
status`, `-get-rendered-head`, `-audit-content-seo`, `-get-inbound-links`, `-audit-
faq-links`. `-get-inbound-links` answers which pages link **to** a page, including
navigation-menu links — the opposite direction from every existing outbound-link
ability.

**Batch 7 — entitlement-gated (6 abilities).** `-get-content-ai-status`, `-manage-
content-ai-prompts`, `-manage-content-ai-output`, `-research-keyword`; `-get-ai-
visibility-brand`, `-update-ai-visibility-object`. Registered **unconditionally**
and gated at runtime, deliberately unlike `register_elementor_pro_abilities()`: 
Content AI and AI Visibility ship in Rank Math _free_ and gate on cloud-account 
registration plus a credit balance, not on a separate plugin, so availability can
change without an activation and cannot be decided at registration time.

**Security.** Every ability requires `manage_options` **and** Rank Math's own granular`
rank_math_*` capability, matching the convention across the rest of the plugin's
ability suites. The floor is uniform across all 61 and declared `final` so it cannot
be lowered per ability. Revoking a capability in Rank Math's Role Manager therefore
genuinely blocks the corresponding ability, which the companion plugin's blanket`
manage_options` ignores. One documented filter, `acrossai_abilities_manager_rank_math_permission`,
lets site owners relax the policy. Twelve abilities are irreversible and require`
confirm: true`. The post-scoped writers additionally perform per-object `edit_post`/`
edit_user` / `edit_terms` checks inside their handler as defence in depth, and the
schema writers verify that a `schema-<meta_id>` row actually belongs to the named
object before writing — Rank Math addresses schema rows by meta id and would otherwise
update a different object's row.

**Data-loss prevention.** Rank Math's settings sanitizer defaults any field it was
not told the type of to single-line text, which strips newlines, and its own field
definitions use _legacy_ CMB2 type names while the sanitizer's cases are the _React_
names — 11 of 19 legacy types match no case. `Settings_Registry` therefore ships
a declarative field-spec table for all 20 panels, mirroring the Rank Math source
with a file citation per panel, and maps legacy names onto the sanitizer's vocabulary.
Verified live with a control: writing `nofollow_domains` with the mapped `textarea`
type preserves newlines, while the identical write using Rank Math's own declared`
textarea_small` stores them collapsed onto one line. Nine multi-line settings were
at risk.

**Notable.** No raw Rank Math option read/write ability ships — the plugin already
provides generic option abilities, and adding Rank Math-branded raw writers would
reintroduce exactly the data-loss path above. No bulk role-capability writer ships
either, because `Helper::set_capabilities()` strips capabilities from roles omitted
from the payload; the existing per-capability abilities cannot trigger that. The`.
htaccess` editor, version rollback and beta opt-in are out of scope.

#### 0.0.27 – 2026-08-14

**Patch release — UI polish + admin-surface rename following the 0.0.26 Feature 
067 rollup.** No new abilities; both entries below are UX-affecting changes to the
admin surface. Plugin version bumped 0.0.26  0.0.27.

 * **Rename — “Ability Library” admin page is now “Ability Integrations”.** The 
   submenu label (“Library”  “Integrations”), page title (“Ability Library”  “Ability
   Integrations”), main heading, and URL slug (`page=acrossai-abilities-library``
   page=acrossai-abilities-integrations`) all updated. Bookmarks / external links
   to the old slug will 404 in wp-admin — update saved links to the new URL. Internal
   class names, hook names, REST endpoint namespace (`/wp-json/acrossai-abilities-
   library/v1/`), and the DOM mount id are …

## Meta

 *  Version **0.0.33**
 *  Last updated **prije 5 dana**
 *  Active installations **Manje od 10**
 *  WordPress version ** 6.9 ili viša **
 *  Tested up to **7.0.4**
 *  PHP version ** 8.1 ili viša **
 *  Language
 * [English (US)](https://wordpress.org/plugins/acrossai-abilities-manager/)
 * Tags
 * [abilities](https://bs.wordpress.org/plugins/tags/abilities/)[access-control](https://bs.wordpress.org/plugins/tags/access-control/)
   [AI](https://bs.wordpress.org/plugins/tags/ai/)[site management](https://bs.wordpress.org/plugins/tags/site-management/)
 *  [Napredni pogled](https://bs.wordpress.org/plugins/acrossai-abilities-manager/advanced/)

## Ocjene

No reviews have been submitted yet.

[Your review](https://wordpress.org/support/plugin/acrossai-abilities-manager/reviews/#new-post)

[See all reviews](https://wordpress.org/support/plugin/acrossai-abilities-manager/reviews/)

## Doprinositelji

 *   [ Deepak Gupta ](https://profiles.wordpress.org/raftaar1191/)

## Podrška

Imate nešto za reći? Trebate pomoć?

 [Pogledaj forum podrške](https://wordpress.org/support/plugin/acrossai-abilities-manager/)

## Pokloni

Da li bi ste željeli da podržite napredovanje ovog proširenja?

 [ Pokloni ovom proširenju ](https://github.com/acrosswp/acrossai-abilities-manager)