From a2f2b5f404ccee8d112114c813e3784be5ae8314 Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Fri, 7 Aug 2026 07:59:40 +0200 Subject: [PATCH 1/5] Fix AI instruction standard to enforce JSON-first styling (LS-2338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add explicit JSON-first/CSS-last-resort rule to AGENTS.md, matching kwv-theme-2026's standard, plus a JSON-vs-CSS gate to the styling auditor agent and pattern-extractor skill so Sass/GSAP/is-styles are only used when theme.json genuinely cannot express the style. Fixes the incorrect claim that styles/blocks/ and styles/sections/ aren't auto-consumed by WordPress (AGENTS.md and theme-json.instructions.md). Integrates Zared's new wp-block-style-audit skill as the authoritative decision procedure. Docs/config only — no theme output changes. --- .../wordpress-theme-styling-auditor.agent.md | 10 +- .agents/skills/pattern-extractor/SKILL.md | 25 +++- .agents/skills/wp-block-style-audit/SKILL.md | 118 ++++++++++++++++++ .../references/block-style-json-anatomy.md | 103 +++++++++++++++ .../instructions/theme-json.instructions.md | 6 +- AGENTS.md | 40 +++++- 6 files changed, 295 insertions(+), 7 deletions(-) create mode 100644 .agents/skills/wp-block-style-audit/SKILL.md create mode 100644 .agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md diff --git a/.agents/agents/wordpress-theme-styling-auditor.agent.md b/.agents/agents/wordpress-theme-styling-auditor.agent.md index 7796994..bdd41e5 100644 --- a/.agents/agents/wordpress-theme-styling-auditor.agent.md +++ b/.agents/agents/wordpress-theme-styling-auditor.agent.md @@ -32,10 +32,10 @@ Find styling-system issues early, explain the root cause, and propose a minimal, ## Operating rules - Read `AGENTS.md`, `.github/instructions/theme-json.instructions.md`, and `.github/instructions/design-token-policy.instructions.md` before making decisions. -- Read `.github/instructions/styling.instructions.md` before making Sass, CSS, or style-JSON recommendations. +- Read `.github/instructions/styling.instructions.md` and `.agents/skills/wp-block-style-audit/SKILL.md` before making Sass, CSS, or style-JSON recommendations. The `wp-block-style-audit` skill is the authoritative procedure for judging whether a CSS rule has a JSON equivalent — use it instead of ad hoc judgment calls. - Audit first. Do not edit files until the user explicitly approves a proposed plan. - Treat `src/scss/` as source and `assets/css/` as compiled output. Do not hand-edit compiled CSS when a source file exists. -- Treat `theme.json`, `styles/**/*.json`, `styles/presets/**/*.json`, and Sass or CSS as one styling system with clear ownership boundaries. +- `theme.json`, `styles/**/*.json`, and `styles/presets/**/*.json` are the styling system. Sass/CSS is a documented exception layer, not a peer — treat any Sass/CSS rule found during audit as a finding to justify or migrate, not as normal architecture. - Use the existing repo scripts `npm run sync:breakpoints`, `npm run build:css`, and `npm run watch:css`. Do not propose Gulp, Grunt, CodeKit, Scout, LiveReload, PurgeCSS, or alternate pipelines unless the user explicitly asks to change the toolchain. - Prefer existing semantic tokens, motion tokens, spacing presets, z-index tokens, and shadow tokens before introducing new values, however if it makes sense for clarity or maintainability, new tokens may be first proposed and then introduced. - Use Sass mixins, maps, functions, and variables only when they remove verified duplication or materially improve clarity. @@ -53,6 +53,12 @@ Find styling-system issues early, explain the root cause, and propose a minimal, ## Audit workflow +0. For every Sass/CSS rule under audit, first classify it: does a JSON equivalent + exist (`elements.*`, `blocks.*`, pseudo-state keys, block attributes)? Use + `.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md` as + the decision table. If yes, flag it as a migration candidate regardless of how + long it's been there. Only rules with no JSON equivalent, and carrying a "JSON + limitation" comment, pass the audit clean. 1. Gather the relevant Sass, CSS, `theme.json`, style JSON, and preset files. 2. Trace repeated values and determine whether they belong in Sass, runtime tokens, or both. 3. Identify duplication, dead utilities, token drift, invalid syntax, brittle selectors, and over-abstraction. diff --git a/.agents/skills/pattern-extractor/SKILL.md b/.agents/skills/pattern-extractor/SKILL.md index 3ddc6f9..b365903 100644 --- a/.agents/skills/pattern-extractor/SKILL.md +++ b/.agents/skills/pattern-extractor/SKILL.md @@ -11,7 +11,7 @@ Use this skill when importing a Figma design into `patterns/` as a production-re Whenever this skill creates or updates authored UI files such as pattern PHP, block style JSON, section style JSON, or theme CSS, it must also load and follow the `theme-color-token-enforcer` skill for those files. Treat `theme-color-token-enforcer` as the authoritative rule set for semantic colour token reuse, token creation, dark-mode parity, and contrast validation. -Whenever this skill decides that a pattern needs GSAP-powered motion, it must also load and follow the `wordpress-gsap` skill. Treat `wordpress-gsap` as the authoritative workflow for WordPress enqueueing, GSAP plugin registration, runtime scoping, and reduced-motion-safe effect architecture. +Whenever the JSON-First Gate below determines that a pattern genuinely needs GSAP-powered motion, this skill must also load and follow the `wordpress-gsap` skill. Treat `wordpress-gsap` as the authoritative workflow for WordPress enqueueing, GSAP plugin registration, runtime scoping, and reduced-motion-safe effect architecture. GSAP is never a default choice — it is only used once the gate confirms CSS cannot do the job. Patterns should be grouped into taxonomy subfolders rather than stored flat at the top level. For example, a single featured card pattern should live at `patterns/cards/feature-card.php`. @@ -129,6 +129,29 @@ Record state deltas explicitly: - base -> focus-visible - base -> active +### Phase 2.5a — JSON-First Gate (mandatory, before any Sass/CSS/GSAP/is-style work) + +For every visual property identified in Phase 2, check in this order before writing +any authored CSS: + +1. Does an existing `styles/**/*.json` partial already cover this? Check sibling + files in the same subfolder first — reuse before creating. +2. Can it be expressed as a new block-style/section-style JSON partial using + `elements.*`, `blocks.*`, pseudo-state keys, or block attributes? Use + `.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md` as + the JSON-vs-CSS decision table. +3. Only if neither applies, and the property has no JSON equivalent (transitions, + transform, `content:""`, aria-selectors, SVG fill, comma-separated selectors), is + authored Sass/CSS permitted — and it must carry a comment naming the specific + limitation, per `AGENTS.md` Theme-First Approach. +4. Do not register a new is-style variant for a single-use, one-off treatment with + no second option ever offered. If it's used in exactly one place, style it inline + on the pattern's block attributes instead of registering a global style-picker + entry. +5. GSAP is permitted only for JS-driven interaction that CSS transition/animation + structurally cannot achieve (e.g. scroll-triggered sequencing, cursor-tracked + spotlight effects) — not as a default for "this pattern has motion." + ### Phase 2.5 — Context-Aware Block Selection Infer the correct WordPress core block from design intent before writing markup. diff --git a/.agents/skills/wp-block-style-audit/SKILL.md b/.agents/skills/wp-block-style-audit/SKILL.md new file mode 100644 index 0000000..65c8b02 --- /dev/null +++ b/.agents/skills/wp-block-style-audit/SKILL.md @@ -0,0 +1,118 @@ +--- +name: wp-block-style-audit +description: "Audit a WordPress block style JSON file (styles/*.json) and migrate CSS selector soup into proper theme.json-style JSON properties — elements, blocks, pseudo-states — leaving only CSS that has no JSON equivalent." +compatibility: "Targets WordPress 6.9+ (theme.json v3). Requires access to the theme's theme.json for preset token names." +--- + +# WP Block Style JSON Audit + +## When to use + +Use this skill when a block style JSON file under `styles/` has a large `css` string doing work that belongs in structured JSON: + +- Colors/backgrounds set via `.wp-block-*` selectors instead of `elements.button`, `elements.link`, etc. +- Nested block styles (link colors on excerpt, terms, paragraph) done via `:where()` CSS instead of `blocks["core/post-excerpt"].elements.link` +- Third-party block colors (outermost/icon-block, etc.) done via CSS instead of `blocks["vendor/block"].color.text` +- Redundant CSS that duplicates what parent `elements` JSON already covers + +## Inputs required + +- Path to the block style JSON file to audit. +- Path to the theme's `theme.json` (to verify preset token names). +- Any sibling block style files that serve as reference patterns. + +## Procedure + +### 1) Read the file and catalogue every CSS rule + +Parse the `css` string into individual selector groups. For each, note: +- What element or block it targets (the `.wp-block-*` class or aria selector) +- What CSS properties it sets +- Whether it involves a pseudo-state (`:hover`, `:focus-visible`, `:active`) +- Whether it depends on a parent-context trigger (e.g., `&:hover .child`) + +Read: +- `references/block-style-json-anatomy.md` + +### 2) Check sibling files for established patterns + +Look at other files in the same `styles/` directory. Prefer patterns already in use over inventing new structure. + +For example in the theme, `styles/sections/cards/card-link-row.json` is the canonical reference for card-style blocks. + +### 3) For each CSS rule, decide: JSON or keep? + +**Move to JSON if the property has a theme.json equivalent:** + +| CSS rule | JSON destination | +|---|---| +| `& .wp-block-button__link { background-color }` | `elements.button.color.background` | +| `& .wp-block-button__link { color }` | `elements.button.color.text` | +| `& .wp-block-button__link:hover { ... }` | `elements.button[":hover"].color` | +| `& .wp-block-post-excerpt__excerpt a { color }` | `blocks["core/post-excerpt"].elements.link.color.text` | +| `& .wp-block-post-excerpt__excerpt a:hover { color }` | `blocks["core/post-excerpt"].elements.link[":hover"].color.text` | +| `& .wp-block-post-terms a { color }` | `blocks["core/post-terms"].elements.link.color.text` | +| `& p a { color }` | `blocks["core/paragraph"].elements.link.color.text` | +| `& .wp-block-outermost-icon-block .icon-container { color }` | `blocks["outermost/icon-block"].color.text` | +| Heading colors | `elements.heading.color.text` | +| `core/post-title` color, typography | `blocks["core/post-title"].color.text` / `.typography` | + +**Keep in `css` if there is no JSON equivalent:** + +- Layout: `overflow`, `max-width`, `width`, `aspect-ratio` (unless `dimensions` is supported) +- Transitions: `transition`, `transform`, `animation` +- Pseudo-states on the block itself: `&:hover { box-shadow }` (block-level hover isn't a JSON key) +- Parent-triggered child selectors: `&:hover .wp-block-cover img { transform }` — hover is on the parent, so must stay at root `css` level +- Aria-label selectors: `& :is([aria-label="..."])` — no JSON key maps to aria +- SVG fill: `& svg { fill: currentColor }` — no JSON equivalent +- `:focus-visible` on buttons — not a supported pseudo-state key, put in `elements.button.css` + +**Remove entirely if redundant:** + +- CSS that re-states a color already set by a parent `elements` JSON key (e.g., `& .wp-block-post-title a { color: contrast }` when `elements.link.color.text` is already `contrast`) + +### 4) Check token references use the correct format + +- In JSON values: use `var:preset|color|slug` (colon-pipe notation) +- In `css` strings: use `var(--wp--preset--color--slug)` (double-dash notation) + +Verify every token slug exists in `theme.json` settings before using it. + +### 5) Split the remaining `css` by owner + +Do **not** leave one monolithic `css` string. Distribute remaining CSS to the nearest owner: + +- Root card behavior → `styles.css` +- Button-specific CSS → `styles.elements.button.css` +- Block-specific CSS → `styles.blocks["vendor/block"].css` + +### 6) Write the refactored file + +- Preserve all top-level metadata: `$schema`, `version`, `title`, `slug`, `blockTypes`, `description` +- Order within `styles`: `border`, `color`, `shadow`, `spacing`, `css` (if any), `elements`, `blocks` +- Order within `elements`: `heading`, `link`, `button`, `separator` (alphabetical within each group) +- Order within `blocks`: core blocks first (alphabetical by block name), then third-party blocks alphabetical + +## Verification + +After editing: + +1. Validate JSON syntax (no trailing commas, balanced braces). +2. Open the block in the Site Editor — confirm the style appears and applies. +3. Hover the block — confirm hover transitions fire. +4. Check buttons: normal state, hover, and focus-visible outline. +5. Confirm link colors in excerpt, terms, and paragraph areas match before/after. +6. Confirm icon block color matches. + +## Failure modes + +- **Token slug not found**: CSS var resolves to empty. Verify slug against `theme.json` `settings.color.palette`. +- **`blocks` key not applying**: Confirm WordPress version supports per-block scoping in block style JSON (requires WP 6.6+). +- **`:hover` on `elements.button` not generating output**: Confirm the block style file targets a block type that supports button elements. +- **Parent hover not working after moving image CSS to `blocks["core/cover"]`**: Image overflow + hover zoom selectors depend on the parent card's `:hover` trigger and **must stay in root `styles.css`**, not in the cover block's own `css`. + +## Escalation + +- Theme.json schema reference: +- Block style API: +- Full Site Editing lessons: diff --git a/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md b/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md new file mode 100644 index 0000000..68c19e3 --- /dev/null +++ b/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md @@ -0,0 +1,103 @@ +# Block Style JSON Anatomy + +Block style JSON files live under `styles/` (or subdirectories like `styles/sections/`). They share the theme.json v3 schema but only contain a subset of keys. + +## Minimal structure + +```json +{ + "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "version": 3, + "title": "Human-readable name", + "slug": "css-class-suffix", + "blockTypes": ["core/group"], + "description": "Optional.", + "styles": { ... } +} +``` + +The block receives the class `is-style-` on its root element. All selectors in `css` use `&` to refer to that root. + +## What `styles` supports + +``` +styles +├── border { radius, color, style, width } +├── color { background, text, gradient } +├── shadow "var:preset|shadow|slug" +├── spacing { blockGap, padding, margin } +├── typography { fontSize, fontFamily, fontWeight, ... } +├── dimensions { minHeight, aspectRatio } +├── css "raw CSS string, & = the block root" +├── elements +│ ├── heading { color, typography } +│ ├── link { color, typography, ":hover", ":focus", ":active", ":visited" } +│ ├── button { color, typography, spacing, border, ":hover", ":focus", ":active", "css" } +│ ├── separator { color } +│ ├── h1–h6 { typography } +│ └── caption { color, typography } +└── blocks + └── "core/post-excerpt" + ├── color, typography, spacing, border, css + └── elements + └── link { color, ":hover", ... } +``` + +## Token formats + +Use `var:preset|type|slug` in JSON values, `var(--wp--preset--type--slug)` in `css` strings. + +```json +"color": { "text": "var:preset|color|accent-500" } +"css": "color: var(--wp--preset--color--accent-500);" +``` + +Custom tokens from `theme.json settings.custom` use `var:custom|path|to|key` / `var(--wp--custom--path--to--key)`. + +## Pseudo-states + +`link` and `button` elements support `:hover`, `:focus`, `:active`, `:visited` as sibling keys: + +```json +"elements": { + "button": { + "color": { "background": "var:preset|color|primary-500" }, + ":hover": { + "color": { "background": "var:preset|color|accent-500" } + }, + "css": "&:focus-visible{ outline: 2px solid ...; }" + } +} +``` + +## `blocks` sub-key + +Allows scoped styles for child blocks. Supported in block style JSON from WP 6.6+. + +```json +"blocks": { + "core/post-excerpt": { + "elements": { + "link": { + "color": { "text": "var:preset|color|accent-500" }, + ":hover": { "color": { "text": "var:preset|color|accent-600" } } + } + } + }, + "outermost/icon-block": { + "color": { "text": "var:preset|color|accent-500" }, + "css": "& svg { fill: currentColor; }" + } +} +``` + +## What must stay in `css` + +| Situation | Reason | +|---|---| +| `overflow`, `max-width`, transitions | No JSON key maps to these properties | +| `&:hover { box-shadow }` on the block root | Block-level hover has no JSON pseudo-state | +| `&:hover .child-selector { transform }` | Hover trigger is the parent; can't live in the child block's `css` | +| `& :is([aria-label="..."])` | No JSON key for aria-label targeting | +| `& svg { fill: currentColor }` | No JSON key for SVG fill | +| `:focus-visible` on buttons | Not a supported pseudo-state key; use `elements.button.css` | diff --git a/.github/instructions/theme-json.instructions.md b/.github/instructions/theme-json.instructions.md index 6a72e01..e0b5af9 100644 --- a/.github/instructions/theme-json.instructions.md +++ b/.github/instructions/theme-json.instructions.md @@ -189,8 +189,10 @@ Reference them from authored CSS or style JSON with `var(--wp--custom--animation - `styles/light.json` and `styles/dark.json` are registered style variations. - Additional variations can be added as `styles/*.json`. -- `styles/blocks/` and `styles/sections/` are organisational conventions — - WordPress does not auto-consume these as global style variations. +- `styles/blocks/` and `styles/sections/` files carry the `blockTypes` + `slug` + schema, which WordPress 6.6+ auto-discovers recursively and registers as live, + editor-facing style-picker entries. Every file here is a real, user-visible + option — do not add one as a one-off hack for a single pattern. - Keep variation files focused — only override what differs from the base `theme.json`. - `styles/dark.json` must mirror the semantic colour token paths from `theme.json`. - Shared non-colour token families such as `settings.custom.animation` and `settings.custom.z-index` do not need matching paths in `styles/dark.json`. diff --git a/AGENTS.md b/AGENTS.md index 7cf7289..ec8fe13 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -71,6 +71,34 @@ Do not add WordPress.org-specific bureaucracy unless there is clear value. ## Theme-First Approach +- `theme.json` and `styles/**/*.json` (block-style and section-style JSON partials) + are the single source of truth for styling. This includes colour, typography, + spacing, layout, borders, shadows, and block-level structural properties. +- Author Sass/CSS in `src/scss/**/*.scss` **only** for what a JSON style genuinely + cannot express: `:hover`/`:focus-within` states not covered by an `elements.*` + pseudo-state key, `content:""` pseudo-elements, comma-separated selectors, SVG + `fill`, aria-attribute selectors, or parent-triggered child-selector motion. See + `.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md` for + the authoritative JSON-vs-CSS decision table. +- Before writing any new Sass/CSS rule, check whether a JSON equivalent already + exists — look at sibling files in `styles/**` for the established pattern first. +- When a CSS rule is genuinely unavoidable, add a comment directly above it naming + the specific limitation that forced it, e.g.: + `// JSON limitation: block-level :hover has no theme.json pseudo-state key — see AGENTS.md Theme-First Approach` +- Structural properties — layout (flex/grid), spacing, sizing, positioning — belong + in JSON or block attributes **always**, never in Sass/CSS, regardless of what + folder or filename the CSS would otherwise land in (a file named "motion" is not + exempt). +- Motion/animation files (`src/scss/animations/**`, `src/scss/gsap/**`) may contain + **only** `@keyframes`, `transition`, `transform`, `animation`, and `will-change` + rules, plus their `prefers-reduced-motion` companions. Any other property in those + files is a defect and must be moved to a JSON style partial or removed. +- GSAP is permitted only for JS-driven interaction that CSS transition/animation + structurally cannot achieve (e.g. scroll-triggered sequencing, cursor-tracked + effects) — never as a default choice for "this pattern has motion." +- Do not register a new `is-style` variant for a single-use, one-off treatment with + no second option ever offered. If it's used in exactly one place, style it inline + on the pattern's block attributes instead of creating a global style-picker entry. - Prefer `theme.json` over PHP for colours, typography, spacing, and layout. - Keep `functions.php` minimal. Only register block supports, enqueue assets, or add editor styles there. - Use `inc/` only for genuine PHP logic that does not belong in `functions.php`. @@ -155,8 +183,11 @@ Rules: - Style variations live in `styles/`. - Two style variations are provided: `light.json` and `dark.json`. - Additional variations can be added as `styles/*.json`. -- `styles/blocks/` and `styles/sections/` are organisational conventions for future per-block or per-section styles. -- These nested JSON files are not automatically consumed by WordPress as global style variations — they are available for reference or tooling. +- `styles/blocks/` and `styles/sections/` files carry the `blockTypes` + `slug` + schema, which WordPress 6.6+ auto-discovers recursively and registers as live, + editor-facing style-picker entries. Every file added here is a real, user-visible + option — do not add one as a one-off hack for a single pattern (see Theme-First + Approach above). - Keep variation files small and focused. --- @@ -228,6 +259,11 @@ composer run lint:php | `.agents/skills/` | Portable, reusable AI skills | | `.agents/agents/` | Agent persona definitions | +Key skill: `.agents/skills/wp-block-style-audit/` — the JSON-vs-CSS decision +procedure for migrating CSS-selector-soup into proper theme.json-style JSON +(`elements`, `blocks`, pseudo-states). Read this before authoring or auditing any +`styles/**/*.json` file or `src/scss/**/*.scss` partial. + --- ## Rules for AI Agents From bd689a017345c277509faaf897aa303bf4b5ccb7 Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Fri, 7 Aug 2026 08:56:41 +0200 Subject: [PATCH 2/5] Update minimum WordPress version requirement to 6.9 --- style.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/style.css b/style.css index eb3ae07..f7b97c9 100644 --- a/style.css +++ b/style.css @@ -5,7 +5,7 @@ Author: LightSpeed Author URI: https://lightspeedwp.agency/ Description: LightSpeed Theme is a custom WordPress block theme built by LightSpeed for fast, accessible, maintainable websites using the WordPress Site Editor and block editor. Version: 0.1.0 -Requires at least: 6.4 +Requires at least: 6.9 Tested up to: 7.0 Requires PHP: 8.1 License: GPL-2.0-or-later @@ -18,4 +18,4 @@ code, pre { font-family: var(--wp--preset--font-family--monospace); font-size: var(--wp--preset--font-size--200); -} \ No newline at end of file +} From bfc0678e9d25693f7bf65987fe424604265fcb92 Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Fri, 7 Aug 2026 09:27:48 +0200 Subject: [PATCH 3/5] Address CodeRabbit/Copilot review feedback on JSON-first instructions (LS-2338) Fix schema URL to match the theme's actual trunk convention, document missing var:custom token syntax, align UK spelling, and scope the JSON-limitation-comment and structural-properties rules to new/modified CSS only so they don't retroactively invalidate existing valid exceptions (e.g. transitions/overflow/max-width that JSON has no key for). Applies to AGENTS.md, the styling auditor agent, and the new wp-block-style-audit skill. --- .../wordpress-theme-styling-auditor.agent.md | 6 ++++-- .agents/skills/wp-block-style-audit/SKILL.md | 13 +++++++----- .../references/block-style-json-anatomy.md | 2 +- AGENTS.md | 20 +++++++++++++------ 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/.agents/agents/wordpress-theme-styling-auditor.agent.md b/.agents/agents/wordpress-theme-styling-auditor.agent.md index bdd41e5..fc20120 100644 --- a/.agents/agents/wordpress-theme-styling-auditor.agent.md +++ b/.agents/agents/wordpress-theme-styling-auditor.agent.md @@ -57,8 +57,10 @@ Find styling-system issues early, explain the root cause, and propose a minimal, exist (`elements.*`, `blocks.*`, pseudo-state keys, block attributes)? Use `.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md` as the decision table. If yes, flag it as a migration candidate regardless of how - long it's been there. Only rules with no JSON equivalent, and carrying a "JSON - limitation" comment, pass the audit clean. + long it's been there. Rules with no JSON equivalent (e.g. `overflow`, + `max-width`, `width`, transitions/transforms) pass clean without a comment if + pre-existing; new or modified rules of this kind must carry a "JSON + limitation" comment going forward. 1. Gather the relevant Sass, CSS, `theme.json`, style JSON, and preset files. 2. Trace repeated values and determine whether they belong in Sass, runtime tokens, or both. 3. Identify duplication, dead utilities, token drift, invalid syntax, brittle selectors, and over-abstraction. diff --git a/.agents/skills/wp-block-style-audit/SKILL.md b/.agents/skills/wp-block-style-audit/SKILL.md index 65c8b02..b44e6d6 100644 --- a/.agents/skills/wp-block-style-audit/SKILL.md +++ b/.agents/skills/wp-block-style-audit/SKILL.md @@ -10,9 +10,9 @@ compatibility: "Targets WordPress 6.9+ (theme.json v3). Requires access to the t Use this skill when a block style JSON file under `styles/` has a large `css` string doing work that belongs in structured JSON: -- Colors/backgrounds set via `.wp-block-*` selectors instead of `elements.button`, `elements.link`, etc. -- Nested block styles (link colors on excerpt, terms, paragraph) done via `:where()` CSS instead of `blocks["core/post-excerpt"].elements.link` -- Third-party block colors (outermost/icon-block, etc.) done via CSS instead of `blocks["vendor/block"].color.text` +- Colours/backgrounds set via `.wp-block-*` selectors instead of `elements.button`, `elements.link`, etc. +- Nested block styles (link colours on excerpt, terms, paragraph) done via `:where()` CSS instead of `blocks["core/post-excerpt"].elements.link` +- Third-party block colours (outermost/icon-block, etc.) done via CSS instead of `blocks["vendor/block"].color.text` - Redundant CSS that duplicates what parent `elements` JSON already covers ## Inputs required @@ -73,10 +73,13 @@ For example in the theme, `styles/sections/cards/card-link-row.json` is the cano ### 4) Check token references use the correct format -- In JSON values: use `var:preset|color|slug` (colon-pipe notation) +- In JSON values: use `var:preset|color|slug` (colon-pipe notation) for preset + tokens, or `var:custom|path|to|key` for custom tokens - In `css` strings: use `var(--wp--preset--color--slug)` (double-dash notation) + for preset tokens, or `var(--wp--custom--path--to--key)` for custom tokens -Verify every token slug exists in `theme.json` settings before using it. +Verify every preset token slug exists in `theme.json` `settings.presets` and +every custom token path exists in `theme.json` `settings.custom` before using it. ### 5) Split the remaining `css` by owner diff --git a/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md b/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md index 68c19e3..51c2bb2 100644 --- a/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md +++ b/.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md @@ -6,7 +6,7 @@ Block style JSON files live under `styles/` (or subdirectories like `styles/sect ```json { - "$schema": "https://schemas.wp.org/wp/6.9/theme.json", + "$schema": "https://schemas.wp.org/trunk/theme.json", "version": 3, "title": "Human-readable name", "slug": "css-class-suffix", diff --git a/AGENTS.md b/AGENTS.md index ec8fe13..ddc1ba9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -82,13 +82,21 @@ Do not add WordPress.org-specific bureaucracy unless there is clear value. the authoritative JSON-vs-CSS decision table. - Before writing any new Sass/CSS rule, check whether a JSON equivalent already exists — look at sibling files in `styles/**` for the established pattern first. -- When a CSS rule is genuinely unavoidable, add a comment directly above it naming - the specific limitation that forced it, e.g.: +- When writing a new or modifying an existing CSS rule that is genuinely + unavoidable, add a comment directly above it naming the specific limitation + that forced it, e.g.: `// JSON limitation: block-level :hover has no theme.json pseudo-state key — see AGENTS.md Theme-First Approach` -- Structural properties — layout (flex/grid), spacing, sizing, positioning — belong - in JSON or block attributes **always**, never in Sass/CSS, regardless of what - folder or filename the CSS would otherwise land in (a file named "motion" is not - exempt). + This applies to new/modified rules going forward — it does not require + retroactively commenting every pre-existing valid CSS exception already in + the codebase. +- Structural properties — layout (flex/grid), spacing, sizing, positioning — use + JSON or block attributes whenever a supported key exists, regardless of what + folder or filename the CSS would otherwise land in (a file named "motion" is + not exempt). Only fall back to Sass/CSS, with a "JSON limitation" comment, + for structural properties JSON genuinely has no key for (e.g. `overflow`, + `max-width`, `width` — see + `.agents/skills/wp-block-style-audit/references/block-style-json-anatomy.md` + for the full list). - Motion/animation files (`src/scss/animations/**`, `src/scss/gsap/**`) may contain **only** `@keyframes`, `transition`, `transform`, `animation`, and `will-change` rules, plus their `prefers-reduced-motion` companions. Any other property in those From 5e12ed35da622b1cd0d270f65198a2a327e2633e Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Fri, 7 Aug 2026 09:43:17 +0200 Subject: [PATCH 4/5] Fix block-root/element mapping and preset paths; sync README WP version (LS-2338) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Distinguish blocks["block/name"].color (block-root) from elements.* (descendant selectors like .wp-block-button__link) in the audit skill's guidance table — these were previously conflated. Correct the token validation reference from the non-existent settings.presets to the real per-category theme.json collections (settings.color.palette, settings.typography.fontSizes, settings.spacing.spacingSizes). Sync README.md's documented WordPress minimum (6.4+ -> 6.9+) with style.css. --- .agents/skills/wp-block-style-audit/SKILL.md | 9 ++++++--- README.md | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.agents/skills/wp-block-style-audit/SKILL.md b/.agents/skills/wp-block-style-audit/SKILL.md index b44e6d6..6bd44eb 100644 --- a/.agents/skills/wp-block-style-audit/SKILL.md +++ b/.agents/skills/wp-block-style-audit/SKILL.md @@ -10,7 +10,8 @@ compatibility: "Targets WordPress 6.9+ (theme.json v3). Requires access to the t Use this skill when a block style JSON file under `styles/` has a large `css` string doing work that belongs in structured JSON: -- Colours/backgrounds set via `.wp-block-*` selectors instead of `elements.button`, `elements.link`, etc. +- Block-root colours/backgrounds set via `.wp-block-*` selectors instead of `blocks["block/name"].color` +- Descendant element colours (e.g. `.wp-block-button__link`, bare `a`) set via CSS instead of `elements.button`, `elements.link`, etc. - Nested block styles (link colours on excerpt, terms, paragraph) done via `:where()` CSS instead of `blocks["core/post-excerpt"].elements.link` - Third-party block colours (outermost/icon-block, etc.) done via CSS instead of `blocks["vendor/block"].color.text` - Redundant CSS that duplicates what parent `elements` JSON already covers @@ -78,8 +79,10 @@ For example in the theme, `styles/sections/cards/card-link-row.json` is the cano - In `css` strings: use `var(--wp--preset--color--slug)` (double-dash notation) for preset tokens, or `var(--wp--custom--path--to--key)` for custom tokens -Verify every preset token slug exists in `theme.json` `settings.presets` and -every custom token path exists in `theme.json` `settings.custom` before using it. +Verify every preset token slug exists in its matching category-specific +`theme.json` collection (e.g. `settings.color.palette`, +`settings.typography.fontSizes`, `settings.spacing.spacingSizes`), and every +custom token path exists in `theme.json` `settings.custom`, before using it. ### 5) Split the remaining `css` by owner diff --git a/README.md b/README.md index 8ba498b..03e3a0a 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ It includes: ## Requirements - **PHP** 8.1+ -- **WordPress** 6.4+ +- **WordPress** 6.9+ - **Node.js** (see `.nvmrc` for version) - **Composer** 2.x From 2c940d0ec05d2844ff1930f00ddf82e41b6b1621 Mon Sep 17 00:00:00 2001 From: Brandonma21 Date: Fri, 7 Aug 2026 09:46:52 +0200 Subject: [PATCH 5/5] Update minimum WordPress version requirement to 6.9+ --- style.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/style.css b/style.css index f7b97c9..f5b1b41 100644 --- a/style.css +++ b/style.css @@ -5,7 +5,7 @@ Author: LightSpeed Author URI: https://lightspeedwp.agency/ Description: LightSpeed Theme is a custom WordPress block theme built by LightSpeed for fast, accessible, maintainable websites using the WordPress Site Editor and block editor. Version: 0.1.0 -Requires at least: 6.9 +Requires at least: 6.9+ Tested up to: 7.0 Requires PHP: 8.1 License: GPL-2.0-or-later