From 9d9b866cc0e776b12f256fa9e05fff6715ef5ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20S=C3=B8derlind?= Date: Sat, 8 Aug 2026 00:35:20 +0200 Subject: [PATCH] prepare-wordpress: Brain Monkey PHP tests, latest deps, WP Copilot instructions --- .well-known/agent-skills/index.json | 2 +- .../agent-skills/prepare-wordpress.tar.gz | Bin 11301 -> 14880 bytes .../skills/prepare-wordpress/SKILL.md | 38 ++++- .../references/composer-setup.md | 11 +- .../references/copilot-instructions.md | 92 ++++++++++++ .../references/php-testing.md | 135 ++++++++++++++++++ .../references/vitest-setup.md | 4 + .../scripts/detect_project.mjs | 8 ++ .../prepare-wordpress/scripts/plan_setup.mjs | 12 +- skills/prepare-wordpress/SKILL.md | 38 ++++- .../references/composer-setup.md | 11 +- .../references/copilot-instructions.md | 92 ++++++++++++ .../references/php-testing.md | 135 ++++++++++++++++++ .../references/vitest-setup.md | 4 + .../scripts/detect_project.mjs | 8 ++ .../prepare-wordpress/scripts/plan_setup.mjs | 12 +- 16 files changed, 585 insertions(+), 17 deletions(-) create mode 100644 plugins/wordpress-skills/skills/prepare-wordpress/references/copilot-instructions.md create mode 100644 plugins/wordpress-skills/skills/prepare-wordpress/references/php-testing.md create mode 100644 skills/prepare-wordpress/references/copilot-instructions.md create mode 100644 skills/prepare-wordpress/references/php-testing.md diff --git a/.well-known/agent-skills/index.json b/.well-known/agent-skills/index.json index 5e47868..18cb954 100644 --- a/.well-known/agent-skills/index.json +++ b/.well-known/agent-skills/index.json @@ -34,7 +34,7 @@ "type": "archive", "description": "Phase-based WordPress project setup workflow with dry-run planning and confirmed apply for predictable scaffolding/standardization.", "url": "https://soderlind.no/.well-known/agent-skills/prepare-wordpress.tar.gz", - "digest": "sha256:9184137e00076315359b4298eeb577beee1dd7353976d1fc463443e565e51b66" + "digest": "sha256:28fd8747a249eddb8308c4d3eb5bfe730db6a3470ab169092fe506b6a1fd26f2" }, { "name": "wp-bump", diff --git a/.well-known/agent-skills/prepare-wordpress.tar.gz b/.well-known/agent-skills/prepare-wordpress.tar.gz index 8a0a9f31085f7049ab237e9da3014bf49926df44..43d8ceb7a7414338038d7cf19fdd01e91674ef5b 100644 GIT binary patch literal 14880 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 S|33b0`uo3|c^&2e-~a%ut6J#* literal 11301 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 **Dependencies:** Do not pin versions — let Composer resolve the latest compatible releases. Run `composer update` periodically to stay current. + +Unit tests mock WordPress functions with **Brain Monkey** (`brain/monkey`, which pulls in `mockery/mockery`), so tests run without a full WordPress install. See: `references/php-testing.md`. + Then merge these scripts into `composer.json` (do not overwrite existing scripts). Replace `` with the actual plugin slug (folder name / text domain). @@ -284,6 +289,9 @@ Completion criterion: `.editorconfig` and `.gitignore` are present, and existing **Skip if `vitest.config.js` already exists.** +Vitest is the JavaScript test runner for this project. Install the latest +releases (no pinned versions): + ```sh npm install --save-dev vitest jsdom ``` @@ -323,6 +331,27 @@ See: `references/i18n-setup.md` Completion criterion: `i18n-map.json`, `languages/`, and i18n npm scripts are present (or explicit skip/defer rationale is recorded). +### 6b) WordPress Copilot coding instructions + +**Skip if `.github/instructions/wordpress.instructions.md` already exists.** + +Add the community WordPress coding, security, and testing rules from +[github/awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/wordpress.instructions.md) +so agents follow WordPress best practices in this project: + +```sh +mkdir -p .github/instructions +curl -fsSL https://raw.githubusercontent.com/github/awesome-copilot/main/instructions/wordpress.instructions.md \ + -o .github/instructions/wordpress.instructions.md +``` + +If `curl` is unavailable or you are offline, create the file manually from +`references/copilot-instructions.md`. + +See: `references/copilot-instructions.md` + +Completion criterion: `.github/instructions/wordpress.instructions.md` exists (downloaded or created manually), or a skip reason is recorded. + ### 7) Cleanup Remove any stray `yarn.lock` file that may have been created by `npx` commands: @@ -350,6 +379,7 @@ Completion criterion: Final report includes per-phase status, skipped reasons, a - `composer validate` passes. - `npm ls` shows no missing peer dependencies for vitest. - Agent skills are present under `~/.copilot/skills/` or `~/.agents/skills/`. +- `.github/instructions/wordpress.instructions.md` exists when the `instructions` phase ran. ## Failure modes / debugging diff --git a/plugins/wordpress-skills/skills/prepare-wordpress/references/composer-setup.md b/plugins/wordpress-skills/skills/prepare-wordpress/references/composer-setup.md index 5351ed9..6dd127e 100644 --- a/plugins/wordpress-skills/skills/prepare-wordpress/references/composer-setup.md +++ b/plugins/wordpress-skills/skills/prepare-wordpress/references/composer-setup.md @@ -2,10 +2,11 @@ ## Dependencies -Install all PHP dev dependencies in one command: +Install all PHP dev dependencies in one command (no pinned versions — Composer +resolves the latest compatible releases): ```sh -composer require --dev phpunit/phpunit wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer pestphp/pest +composer require --dev phpunit/phpunit brain/monkey wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer pestphp/pest ``` ### What each package does @@ -13,10 +14,16 @@ composer require --dev phpunit/phpunit wp-coding-standards/wpcs dealerdirect/php | Package | Purpose | | --- | --- | | `phpunit/phpunit` | PHP unit testing framework | +| `brain/monkey` | Mocks WordPress core functions/hooks in unit tests (pulls in `mockery/mockery`) so tests run without a WordPress install | | `wp-coding-standards/wpcs` | WordPress PHP Coding Standards ruleset for PHP_CodeSniffer | | `dealerdirect/phpcodesniffer-composer-installer` | Auto-registers PHPCS standards (including WPCS) with Composer | | `pestphp/pest` | Elegant PHP testing framework built on PHPUnit | +> **Latest versions:** Do not pin versions in `composer require`. Run +> `composer update` periodically to pick up new compatible releases. + +For how to write unit tests with Brain Monkey, see `php-testing.md`. + ## Scripts Merge these scripts into `composer.json`. Do NOT overwrite existing scripts — only add missing keys. diff --git a/plugins/wordpress-skills/skills/prepare-wordpress/references/copilot-instructions.md b/plugins/wordpress-skills/skills/prepare-wordpress/references/copilot-instructions.md new file mode 100644 index 0000000..8eb1021 --- /dev/null +++ b/plugins/wordpress-skills/skills/prepare-wordpress/references/copilot-instructions.md @@ -0,0 +1,92 @@ +# WordPress Copilot Coding Instructions + +This phase adds a project-scoped Copilot instructions file so agents follow +WordPress coding, security, i18n, performance, and testing best practices. + +Source: [github/awesome-copilot](https://github.com/github/awesome-copilot/blob/main/instructions/wordpress.instructions.md) +(MIT License). Prefer downloading the canonical file so it stays current. + +## Preferred: download the latest + +```sh +mkdir -p .github/instructions +curl -fsSL https://raw.githubusercontent.com/github/awesome-copilot/main/instructions/wordpress.instructions.md \ + -o .github/instructions/wordpress.instructions.md +``` + +The `applyTo` frontmatter in that file scopes the rules to WordPress plugin, +theme, PHP, JS, and CSS paths automatically. + +## Fallback: create manually (offline) + +If `curl` is unavailable, create `.github/instructions/wordpress.instructions.md` +with the content below. This is a condensed version adapted from +github/awesome-copilot (MIT); replace it with the canonical file when online. + +````markdown +--- +applyTo: 'wp-content/plugins/**,wp-content/themes/**,**/*.php,**/*.inc,**/*.js,**/*.jsx,**/*.ts,**/*.tsx,**/*.css,**/*.scss,**/*.json' +description: 'Coding, security, and testing rules for WordPress plugins and themes' +--- + +# WordPress Development — Copilot Instructions + +Generate WordPress code that is secure, performant, testable, and compliant with +official WordPress practices. Prefer hooks, small functions, and clear separation +of concerns. + +## Core principles +- Never modify WordPress core. Extend via actions and filters. +- Guard entry PHP files with `defined('ABSPATH') || exit;` and a plugin header. +- Use unique prefixes or PHP namespaces to avoid global collisions. +- Enqueue assets; never inline raw `