feat(rules): the custom_css rule target — SiteAgent 2.20.0 (Aura#576, Plan A) - #135
Conversation
…recise CSS-only evidence (Aura#576) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ouch (review r1) An allow admits a call only when every custom_css touch it declared is precise — a single exact touch riding alongside a conservative, create-time (custom_css:*) or unknown (unknown:*) declaration no longer buys the whole call an allow verdict (controller ruling overrides the brief allow branch). CSS_EXACT_PREFIX is now private const. Adds coverage for the three over-permit cases, a still-admitted mixed page/post touch, a target with no id key at all, and enforceable_match() on a CSS allow winner. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…possible CSS for block/warn (Aura#576) Task 2 of Plan A (SiteAgent 2.20.0): Aura_Worker_Rules::fork_css_state() reads ELEMENTOR_MCP_VERSION and reports precise/widened/absent; a new private widen_for_old_fork(), called first in enforce(), synthesises a custom_css:<id> (or custom_css:* for a site write) touch alongside a widened fork's own page/post/site touches — never for other tools, never carrying evidence fields, so no allow rule can be satisfied by it. Test seam _set_fork_version_for_tests() added for fork_css_state(); wired into tests/bootstrap.php's sa_reset_state(). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…amed arguments, conservative from compositions (Aura#576) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…nst its schema, at test and at run time (Aura#576) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t 1.37.0 (final review) A version number is not a capability. fork_css_state() now returns 'precise' only when ELEMENTOR_MCP_VERSION >= 1.37.0 AND the fork ships Elementor_MCP_Rules::css_touches(); a loaded fork failing either is 'widened', so a 1.37.0 released without the matcher keeps its page writes counted as possible CSS instead of silently escaping block custom_css. The test seam takes an optional capability flag (null = method_exists). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…s fail closed (final review)
- update-page-settings `settings` and a manage-elements op's `settings`
that are non-null and not an array are CSS of unknown shape, never
css_only (M1).
- css_value(): an empty array clears; every other non-string non-null
value (false, 0, 0.0, numbers, non-empty arrays, objects) is unknown.
- css_capable_paths(): tuple `items`, anyOf/oneOf/allOf and
patternProperties count as CSS-capable at their node; nested arrays are
descended. A bare {type: object} stays closed (controller ruling). The
4.3 fixture classification is unchanged.
- Test WP_Ability stub gains get_input_schema(), so the production live
schema read is covered; tests for the manage-elements producer guard,
a null live schema, and the CSS touch as touches_for() returns it.
- Drop a redundant (string) cast.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… and preview docs (final review) test_widening_never_speaks_for_allow now asks match() directly with the touch set enforce() builds (a precise control admits, the widened touch does not) and pairs the allow with a warn under enforce(). The fork version seam gains @SInCE 2.20.0, and preview_tool() documents why it does not apply old-fork widening (no elementor-mcp ability reaches it). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 92c07cb338
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| && isset( $t['precise'], $t['css_only'] ) | ||
| && true === $t['precise'] | ||
| && true === $t['css_only'] ) { | ||
| $set[ self::CSS_EXACT_PREFIX . $id ] = true; |
There was a problem hiding this comment.
Preserve conservative duplicate CSS touches
When two declarations name the same CSS target and only one carries exact evidence, normalization retains the shared custom_css:42 key and adds custom_css!exact:42, losing the second declaration's conservative status. Consequently, an allow custom_css:42 rule admits inputs such as one precise CSS-only touch plus one conservative touch for ID 42, despite the intended requirement that every CSS touch be exact. Track inexactness per ID rather than allowing any exact duplicate to certify the normalized target.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 786d4fe — a custom_css id keeps its exact key only if every touch on that id is precise+css_only; exact + conservative on the same id no longer satisfies allow custom_css:<id> (block still matches). Test added.
| foreach ( array( 'anyOf', 'oneOf', 'allOf' ) as $combinator ) { | ||
| if ( isset( $schema[ $combinator ] ) ) { | ||
| $out[] = $here; |
There was a problem hiding this comment.
Distinguish unknown schema shapes from handled paths
For a combinator located at an already handled path, this emits only that ordinary path and never examines its branches. For example, if update-page-settings.settings becomes a oneOf whose new branch carries extra_css, the scanner returns only settings; because that path is already in PRODUCER_HANDLED_PATHS, the drift check remains precise, while the runtime parser ignores extra_css and emits no CSS touch. A live custom_css block can therefore be bypassed after exactly the schema evolution this guard is meant to fail closed on; represent unresolved combinators separately or recurse through their branches.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in ddad64a — a combinator / patternProperties / tuple now surfaces as <path>{unresolved}, which no handled or exempt list names, so it always turns the slug conservative; branches are not descended. Tests: producer whose settings becomes oneOf, and manage-classes whose exempt operations[].css becomes anyOf, both declare conservatively.
…dex r1 on #135) normalize_touches() minted custom_css!exact:<id> from any one exact touch, so an exact and a conservative touch on the same id read as exact and allow custom_css:<id> admitted the call. Exactness is now tracked per id: one inexact touch on an id removes its exact key. Block/warn unchanged. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…or exempt path (Codex r1 on #135) A combinator, patternProperties or tuple items at a path already on PRODUCER_HANDLED_PATHS or a NO_CSS exempt list (settings -> oneOf with an extra_css branch) emitted only the plain path, so the drift check passed and the new branch was never read. Such nodes now surface as `<path>{unresolved}`, which no list names, so the write turns conservative. The 4.3 fixture has none of these shapes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ddad64a9e4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Whether this site's elementor-mcp can say a write carried CSS (2.20.0, | ||
| // Aura spec 2026-09-24 §4.2). An OBJECT on the wire, like `unbound`. | ||
| $status['css_rules'] = (object) array( 'fork' => Aura_Worker_Rules::fork_css_state() ); |
There was a problem hiding this comment.
Bump the advertised plugin version before release
This release identifies the new behavior as 2.20.0, but the plugin header, AURA_WORKER_VERSION, and readme.txt stable tag all remain at 2.19.3. Consequently, an existing 2.19.3 installation cannot receive this build through the normal Aura self-update path: class-aura-worker-updater.php explicitly rejects a package whose version equals the installed version before installing it. Update all three version declarations so this release can actually be deployed and reported as 2.20.0.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Declined for this PR, by procedure: the version bump to 2.20.0 (plugin header, AURA_WORKER_VERSION, readme stable tag, changelog) ships in the separate release PR opened after this feature PR merges — as stated in the PR body. Nothing is deployed from this branch.
| $css_only = false; | ||
| } else { | ||
| $settings = isset( $input['settings'] ) ? $input['settings'] : array(); | ||
| $found = array_key_exists( 'custom_css', $settings ) ? self::css_value( $settings['custom_css'] ) : 'none'; |
There was a problem hiding this comment.
Treat unknown open page settings as conservative CSS
When update-page-settings.settings contains a CSS-bearing key other than exactly custom_css, this assigns none and later emits no custom_css touch, so a block custom_css rule is bypassed. Fresh evidence beyond the previously fixed combinator case is that the checked-in 4.3 schema already declares settings.additionalProperties: true; Elementor can begin interpreting a key such as extra_css without changing that schema, while the drift scanner continues to return only the already-handled settings path. CSS-like or otherwise unrecognized keys inside this open container need a conservative touch rather than being treated as no CSS.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 45a552c — in update-page-settings settings and each manage-elements op's settings, any non-empty key matching /css/i other than custom_css is CSS of unknown shape (conservative touch, not css_only). Exceptions: _css_classes (class names) and css_filters* (structured filter controls). *_style keys are deliberately not matched — element settings are full of style controls. Tests added.
…known shape (Codex r2 on #135) update-page-settings `settings` is additionalProperties: true in the 4.3 schema, so Elementor could start honouring e.g. `extra_css` there with no schema drift the scanner would see. In page settings and in each manage-elements op's settings, a non-empty key matching /css/i other than custom_css now makes the write conservative (no evidence, not css_only). `_css_classes` and the `css_filters*` control group stay ordinary keys; `style` is not matched (element settings are full of *_style controls). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Implements Plan A of the
custom_cssrule target (Digitizers/Aura#576): Digitizers/Auradocs/superpowers/plans/2026-09-24-custom-css-plan-a-siteagent-2-20.md, specdocs/superpowers/specs/2026-09-24-custom-css-rule-target-design.md. Ships as SiteAgent 2.20.0 — no version bump here; the release PR follows on approval.What changes
class-aura-worker-rules.php) — new target typecustom_css(id = post id, or id-less /*= every page, element and kit).block/warnignore evidence and over-block:custom_css:<id>matchescustom_css:<id>orcustom_css:*; id-less matches any custom_css touch;unknown:*matches every live custom_css block/warn.allowneeds a touch withprecise: trueandcss_only: true(literaltrueonly), and fails closed at the set level: nounknown:*, nocustom_css:*, everycustom_css:<id>has its exact twin.enforce()only (whereallownever speaks): a tool namedelementor-mcp/…from a fork that cannot declare CSS turnspage:/post:<id>intocustom_css:<id>too, andsite:*intocustom_css:*. A fork counts as precise only when it is ≥ 1.37.0 and hasElementor_MCP_Rules::css_touches()(Plan B) — a version number alone is not a capability.class-elementor-door-governor.php) — everyWRITE_TABLEslug is in exactly one ofCSS_PRODUCERS/NO_CSS:update-page-settingsandmanage-elementsare precise: CSS is read from named arguments, and any other field makes the call mixed.build-compositionandmanage-component(site-wide) are conservative.design_system(ruling R1).touches_for()appends the CSS declaration to every kind.NO_CSSslug or precise producer whose live input schema grew an unhandled CSS-capable path declares conservatively. Unknown schema shapes (tuple items,anyOf/oneOf/allOf,patternProperties, nested arrays) fail closed./status—css_rules: { fork: "precise" | "widened" | "absent" }, always an object.Clearing is not CSS:
nullor an empty-after-trim string declares nothing. Any other non-string value, and a non-arraysettings, is CSS of unknown shape, so the call gets a custom_css touch with no evidence: block/warn match it and allow does not.Known limits (not changed here)
block custom_cssrule is live.<style>tag inside an HTML widget's content is not treated as custom CSS (spec ruling R5, out of scope).{type: object}parameter with no declared properties is treated as closed. Counting it as open would makemanage-elementspermanently conservative throughoperations[].interactions[].Verification
vendor/bin/phpunit: OK, 5509 tests (the 10 deprecations were already there before this branch).vendor/bin/phpcs: 0 errors, and no new warnings.RulesCustomCssMatchTest,RulesOldForkWideningTest,ElementorDoorCssTouchesTest,ElementorDoorCssClassificationTest,StatusCssRulesTest.🤖 Generated with Claude Code