wordpress-agent-kit 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/skills/blueprint/SKILL.md +418 -0
- package/.github/skills/wp-abilities-api/SKILL.md +12 -0
- package/.github/skills/wp-abilities-api/references/delegate-helper-pattern.md +241 -0
- package/.github/skills/wp-abilities-api/references/domain-vs-projection.md +113 -0
- package/.github/skills/wp-abilities-api/references/error-code-vocabulary.md +123 -0
- package/.github/skills/wp-abilities-api/references/grouping-heuristic.md +89 -0
- package/.github/skills/wp-abilities-api/references/input-schema-gotchas.md +265 -0
- package/.github/skills/wp-abilities-api/references/php-registration.md +47 -20
- package/.github/skills/wp-abilities-api/references/plugin-family-patterns.md +233 -0
- package/.github/skills/wp-abilities-api/references/shared-core-service.md +184 -0
- package/.github/skills/wp-abilities-audit/SKILL.md +199 -0
- package/.github/skills/wp-abilities-audit/references/audit-schema.md +300 -0
- package/.github/skills/wp-abilities-audit/references/capability-gate-tracing.md +197 -0
- package/.github/skills/wp-abilities-audit/references/controller-enumeration.md +116 -0
- package/.github/skills/wp-abilities-verify/SKILL.md +215 -0
- package/.github/skills/wp-abilities-verify/references/annotation-correctness.md +154 -0
- package/.github/skills/wp-abilities-verify/references/audit-schema-validation.md +131 -0
- package/.github/skills/wp-abilities-verify/references/permission-roundtrip.md +190 -0
- package/.github/skills/wp-abilities-verify/references/runtime-harness.md +462 -0
- package/.github/skills/wp-abilities-verify/references/schema-lints.md +118 -0
- package/.github/skills/wp-abilities-verify/references/static-enumeration.md +126 -0
- package/.github/skills/wp-playground/SKILL.md +132 -1
- package/.github/skills/wp-playground/references/e2e-playwright.md +115 -0
- package/.github/skills/wp-plugin-directory-guidelines/SKILL.md +133 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/gpl-compliance.md +217 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/guideline-review-checklist.md +592 -0
- package/.github/skills/wp-plugin-directory-guidelines/references/naming-rules.md +121 -0
- package/.github/skills/wp-project-triage/scripts/detect_wp_project.mjs +22 -4
- package/.github/skills/wp-wpengine/SKILL.md +127 -0
- package/README.md +14 -8
- package/dist/lib/api.js +43 -19
- package/dist/lib/installer.js +0 -2
- package/extensions/wp-agent-kit/index.ts +146 -324
- package/package.json +1 -1
- package/skills-custom/wp-wpengine/SKILL.md +127 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: blueprint
|
|
3
|
+
description: Use when creating, editing, or reviewing WordPress Playground blueprint JSON files. Triggers on mentions of blueprints, playground configuration, or requests to set up a WordPress demo environment.
|
|
4
|
+
license: GPL-2.0-or-later
|
|
5
|
+
compatibility: "WordPress 6.9+, PHP 7.2.24+. Optionally Playground CLI or a browser"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# WordPress Playground Blueprints
|
|
9
|
+
|
|
10
|
+
## Overview
|
|
11
|
+
|
|
12
|
+
A Blueprint is a JSON file that declaratively configures a WordPress Playground instance — installing plugins/themes, setting options, running PHP/SQL, manipulating files, and more.
|
|
13
|
+
|
|
14
|
+
**Core principle:** Blueprints are trusted JSON-only declarations. No arbitrary JavaScript. They work on web, Node.js, and CLI.
|
|
15
|
+
|
|
16
|
+
## Quick Start Template
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
|
|
21
|
+
"landingPage": "/wp-admin/",
|
|
22
|
+
"preferredVersions": { "php": "8.3", "wp": "latest" },
|
|
23
|
+
"steps": [{ "step": "login" }]
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Top-Level Properties
|
|
28
|
+
|
|
29
|
+
All optional. Only documented keys are allowed — the schema rejects unknown properties.
|
|
30
|
+
|
|
31
|
+
| Property | Type | Notes |
|
|
32
|
+
|----------|------|-------|
|
|
33
|
+
| `$schema` | string | Always `"https://playground.wordpress.net/blueprint-schema.json"` |
|
|
34
|
+
| `landingPage` | string | Relative path, e.g. `/wp-admin/` |
|
|
35
|
+
| `meta` | object | `{ title, author, description?, categories? }` — title and author required |
|
|
36
|
+
| `preferredVersions` | object | `{ php, wp }` — both required when present |
|
|
37
|
+
| `features` | object | `{ networking?: boolean, intl?: boolean }` — **only** these two keys, nothing else. Networking defaults to `true` |
|
|
38
|
+
| `extraLibraries` | array | `["wp-cli"]` — auto-included when any `wp-cli` step is present |
|
|
39
|
+
| `constants` | object | Shorthand for `defineWpConfigConsts`. Values: string/boolean/number |
|
|
40
|
+
| `plugins` | array | Shorthand for `installPlugin` steps. Strings = wp.org slugs |
|
|
41
|
+
| `siteOptions` | object | Shorthand for `setSiteOptions` |
|
|
42
|
+
| `login` | boolean or object | `true` = login as admin. Object = `{ username?, password? }` (both default to `"admin"`/`"password"`) |
|
|
43
|
+
| `steps` | array | Main execution pipeline. Runs after shorthands |
|
|
44
|
+
|
|
45
|
+
### preferredVersions Values
|
|
46
|
+
|
|
47
|
+
- **php:** Major.minor only (e.g. `"8.3"`, `"7.4"`), or `"latest"`. Patch versions like `"7.4.1"` are invalid. Check the schema for currently supported versions.
|
|
48
|
+
- **wp:** Recent major versions (e.g. `"6.7"`, `"6.8"`), `"latest"`, `"nightly"`, `"beta"`, or a URL to a custom zip. Check the schema for the full list.
|
|
49
|
+
|
|
50
|
+
### Shorthands vs Steps
|
|
51
|
+
|
|
52
|
+
Shorthands (`login`, `plugins`, `siteOptions`, `constants`) are expanded and prepended to `steps` in an **unspecified order**. Use explicit steps when execution order matters.
|
|
53
|
+
|
|
54
|
+
## Resource References
|
|
55
|
+
|
|
56
|
+
Resources tell Playground where to find files. Used by `installPlugin`, `installTheme`, `writeFile`, `writeFiles`, `importWxr`, etc.
|
|
57
|
+
|
|
58
|
+
| Resource Type | Required Fields | Example |
|
|
59
|
+
|--------------|----------------|---------|
|
|
60
|
+
| `wordpress.org/plugins` | `slug` | `{ "resource": "wordpress.org/plugins", "slug": "woocommerce" }` |
|
|
61
|
+
| `wordpress.org/themes` | `slug` | `{ "resource": "wordpress.org/themes", "slug": "astra" }` |
|
|
62
|
+
| `url` | `url` | `{ "resource": "url", "url": "https://example.com/plugin.zip" }` |
|
|
63
|
+
| `git:directory` | `url`, `ref` | See below |
|
|
64
|
+
| `literal` | `name`, `contents` | `{ "resource": "literal", "name": "file.txt", "contents": "hello" }` |
|
|
65
|
+
| `literal:directory` | `name`, `files` | See below |
|
|
66
|
+
| `bundled` | `path` | References a file within a blueprint bundle (e.g. `{ "resource": "bundled", "path": "/plugin.zip" }`) |
|
|
67
|
+
| `zip` | `inner` | Wraps another resource in a ZIP — use when a step expects a zip but your source isn't one (e.g. wrapping a `url` resource pointing to a raw directory) |
|
|
68
|
+
|
|
69
|
+
### git:directory — Installing from GitHub
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"resource": "git:directory",
|
|
74
|
+
"url": "https://github.com/WordPress/gutenberg",
|
|
75
|
+
"ref": "trunk",
|
|
76
|
+
"refType": "branch",
|
|
77
|
+
"path": "/"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- When using a branch or tag name for `ref`, you **must** set `refType` (`"branch"` | `"tag"` | `"commit"` | `"refname"`). Without it, only `"HEAD"` resolves reliably.
|
|
82
|
+
- `path` selects a subdirectory (defaults to repo root).
|
|
83
|
+
|
|
84
|
+
### literal:directory — Inline File Trees
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"resource": "literal:directory",
|
|
89
|
+
"name": "my-plugin",
|
|
90
|
+
"files": {
|
|
91
|
+
"plugin.php": "<?php /* Plugin Name: My Plugin */ ?>",
|
|
92
|
+
"includes": {
|
|
93
|
+
"helper.php": "<?php // helper code ?>"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
- `files` uses nested objects for subdirectories — keys are filenames or directory names, values are **plain strings** (file content) or **objects** (subdirectories). Never use resource references as values.
|
|
100
|
+
- **Do NOT use path separators in keys** (e.g. `"includes/helper.php"` is wrong — use a nested `"includes": { "helper.php": "..." }` object).
|
|
101
|
+
|
|
102
|
+
## Steps Reference
|
|
103
|
+
|
|
104
|
+
Every step requires `"step": "<name>"`. Any step can optionally include `"progress": { "weight": 1, "caption": "Installing..." }` for UI feedback.
|
|
105
|
+
|
|
106
|
+
### Plugin & Theme Installation
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"step": "installPlugin",
|
|
111
|
+
"pluginData": { "resource": "wordpress.org/plugins", "slug": "gutenberg" },
|
|
112
|
+
"options": { "activate": true, "targetFolderName": "gutenberg" },
|
|
113
|
+
"ifAlreadyInstalled": "overwrite"
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{
|
|
119
|
+
"step": "installTheme",
|
|
120
|
+
"themeData": { "resource": "wordpress.org/themes", "slug": "twentytwentyfour" },
|
|
121
|
+
"options": { "activate": true, "importStarterContent": true },
|
|
122
|
+
"ifAlreadyInstalled": "overwrite"
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
- Use `pluginData` / `themeData` — **NOT** the deprecated `pluginZipFile` / `themeZipFile`.
|
|
127
|
+
- `pluginData` / `themeData` accept any FileReference or DirectoryReference — a zip URL, a `wordpress.org/plugins` slug, a `git:directory`, or a `literal:directory` (no `zip` wrapper needed).
|
|
128
|
+
- `options.activate` controls activation. No need for a separate `activatePlugin`/`activateTheme` step when using `installPlugin`/`installTheme`.
|
|
129
|
+
- `ifAlreadyInstalled`: `"overwrite"` | `"skip"` | `"error"`
|
|
130
|
+
|
|
131
|
+
### Activation (standalone)
|
|
132
|
+
|
|
133
|
+
Only needed for plugins/themes already on disk (e.g. after `writeFile`/`writeFiles`):
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{ "step": "activatePlugin", "pluginPath": "my-plugin/my-plugin.php" }
|
|
137
|
+
```
|
|
138
|
+
```json
|
|
139
|
+
{ "step": "activateTheme", "themeFolderName": "twentytwentyfour" }
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### File Operations
|
|
143
|
+
|
|
144
|
+
```json
|
|
145
|
+
{ "step": "writeFile", "path": "/wordpress/wp-content/mu-plugins/custom.php", "data": "<?php // code" }
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`data` accepts a plain string (as shown above) or a resource reference (e.g. `{ "resource": "url", "url": "https://..." }`).
|
|
149
|
+
|
|
150
|
+
```json
|
|
151
|
+
{
|
|
152
|
+
"step": "writeFiles",
|
|
153
|
+
"writeToPath": "/wordpress/wp-content/plugins/",
|
|
154
|
+
"filesTree": {
|
|
155
|
+
"resource": "literal:directory",
|
|
156
|
+
"name": "my-plugin",
|
|
157
|
+
"files": {
|
|
158
|
+
"plugin.php": "<?php\n/*\nPlugin Name: My Plugin\n*/",
|
|
159
|
+
"includes": {
|
|
160
|
+
"helpers.php": "<?php // helpers"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**`writeFiles` requires a DirectoryReference** (`literal:directory` or `git:directory`) as `filesTree` — not a plain object.
|
|
168
|
+
|
|
169
|
+
Other file operations: `mkdir`, `cp`, `mv`, `rm`, `rmdir`, `unzip`.
|
|
170
|
+
|
|
171
|
+
### Running Code
|
|
172
|
+
|
|
173
|
+
**runPHP:**
|
|
174
|
+
```json
|
|
175
|
+
{ "step": "runPHP", "code": "<?php require '/wordpress/wp-load.php'; update_option('key', 'value');" }
|
|
176
|
+
```
|
|
177
|
+
**GOTCHA:** You must `require '/wordpress/wp-load.php';` to use any WordPress functions.
|
|
178
|
+
|
|
179
|
+
**wp-cli:**
|
|
180
|
+
```json
|
|
181
|
+
{ "step": "wp-cli", "command": "wp post create --post_type=page --post_title='Hello' --post_status=publish" }
|
|
182
|
+
```
|
|
183
|
+
The step name is `wp-cli` (with hyphen), NOT `cli` or `wpcli`.
|
|
184
|
+
|
|
185
|
+
**runSql:**
|
|
186
|
+
```json
|
|
187
|
+
{ "step": "runSql", "sql": { "resource": "literal", "name": "q.sql", "contents": "UPDATE wp_options SET option_value='val' WHERE option_name='key';" } }
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Site Configuration
|
|
191
|
+
|
|
192
|
+
```json
|
|
193
|
+
{ "step": "setSiteOptions", "options": { "blogname": "My Site", "blogdescription": "A tagline" } }
|
|
194
|
+
```
|
|
195
|
+
```json
|
|
196
|
+
{ "step": "defineWpConfigConsts", "consts": { "WP_DEBUG": true } }
|
|
197
|
+
```
|
|
198
|
+
```json
|
|
199
|
+
{ "step": "setSiteLanguage", "language": "en_US" }
|
|
200
|
+
```
|
|
201
|
+
```json
|
|
202
|
+
{ "step": "defineSiteUrl", "siteUrl": "https://example.com" }
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Other Steps
|
|
206
|
+
|
|
207
|
+
| Step | Key Properties |
|
|
208
|
+
|------|---------------|
|
|
209
|
+
| `login` | `username?`, `password?` (default `"admin"` / `"password"`) |
|
|
210
|
+
| `enableMultisite` | (no required props) |
|
|
211
|
+
| `importWxr` | `file` (FileReference) |
|
|
212
|
+
| `importThemeStarterContent` | `themeSlug?` |
|
|
213
|
+
| `importWordPressFiles` | `wordPressFilesZip`, `pathInZip?` — imports a full WordPress directory from a zip |
|
|
214
|
+
| `request` | `request: { url, method?, headers?, body? }` |
|
|
215
|
+
| `updateUserMeta` | `userId`, `meta` |
|
|
216
|
+
| `runWpInstallationWizard` | `options?` — runs the WP install wizard with given options |
|
|
217
|
+
| `resetData` | (no props) |
|
|
218
|
+
|
|
219
|
+
## Common Patterns
|
|
220
|
+
|
|
221
|
+
### Inline mu-plugin (quick custom code)
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"step": "writeFile",
|
|
226
|
+
"path": "/wordpress/wp-content/mu-plugins/custom.php",
|
|
227
|
+
"data": "<?php\n// mu-plugins load automatically — no activation needed, no require wp-load.php\nadd_filter('show_admin_bar', '__return_false');"
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Inline plugin with multiple files
|
|
232
|
+
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"step": "writeFiles",
|
|
236
|
+
"writeToPath": "/wordpress/wp-content/plugins/",
|
|
237
|
+
"filesTree": {
|
|
238
|
+
"resource": "literal:directory",
|
|
239
|
+
"name": "my-plugin",
|
|
240
|
+
"files": {
|
|
241
|
+
"my-plugin.php": "<?php\n/*\nPlugin Name: My Plugin\n*/\nrequire __DIR__ . '/includes/main.php';",
|
|
242
|
+
"includes": {
|
|
243
|
+
"main.php": "<?php // main logic"
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Then activate it with a separate step:
|
|
251
|
+
|
|
252
|
+
```json
|
|
253
|
+
{ "step": "activatePlugin", "pluginPath": "my-plugin/my-plugin.php" }
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Plugin from a GitHub branch
|
|
257
|
+
|
|
258
|
+
```json
|
|
259
|
+
{
|
|
260
|
+
"step": "installPlugin",
|
|
261
|
+
"pluginData": {
|
|
262
|
+
"resource": "git:directory",
|
|
263
|
+
"url": "https://github.com/user/repo",
|
|
264
|
+
"ref": "feature-branch",
|
|
265
|
+
"refType": "branch",
|
|
266
|
+
"path": "/"
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Common Mistakes
|
|
272
|
+
|
|
273
|
+
| Mistake | Correct |
|
|
274
|
+
|---------|---------|
|
|
275
|
+
| `pluginZipFile` / `themeZipFile` | `pluginData` / `themeData` |
|
|
276
|
+
| `"step": "cli"` | `"step": "wp-cli"` |
|
|
277
|
+
| Flat object as `writeFiles.filesTree` | Must be a `literal:directory` or `git:directory` resource |
|
|
278
|
+
| Path separators in `files` keys | Use nested objects for subdirectories |
|
|
279
|
+
| `runPHP` without `wp-load.php` | Always `require '/wordpress/wp-load.php';` for WP functions |
|
|
280
|
+
| Invented top-level keys | Only documented keys work — schema rejects unknown properties |
|
|
281
|
+
| Inventing proxy URLs for GitHub | Use `git:directory` resource type |
|
|
282
|
+
| Omitting `refType` with branch/tag `ref` | Required — only `"HEAD"` works without it |
|
|
283
|
+
| Resource references in `literal:directory` `files` values | Values must be plain strings (content) or objects (subdirectories) — never resource refs |
|
|
284
|
+
| `features.debug` or other invented feature keys | `features` only supports `networking` and `intl` — use `constants: { "WP_DEBUG": true }` for debug mode |
|
|
285
|
+
| `require wp-load.php` in mu-plugin code | Only needed in `runPHP` steps — mu-plugins already run within WordPress |
|
|
286
|
+
| Schema URL with `.org` domain | Must be `playground.wordpress.net`, not `playground.wordpress.org` |
|
|
287
|
+
|
|
288
|
+
## Full Reference
|
|
289
|
+
|
|
290
|
+
This skill covers the most common steps and patterns. For the complete API, see:
|
|
291
|
+
|
|
292
|
+
- **Blueprint docs:** https://wordpress.github.io/wordpress-playground/blueprints
|
|
293
|
+
- **JSON schema:** https://playground.wordpress.net/blueprint-schema.json
|
|
294
|
+
|
|
295
|
+
Additional steps not covered above: `runPHPWithOptions` (run PHP with custom `ini` settings), `runWpInstallationWizard`, and resource types `vfs` and `bundled` (for advanced embedding scenarios).
|
|
296
|
+
|
|
297
|
+
## Blueprint Bundles
|
|
298
|
+
|
|
299
|
+
Bundles are self-contained packages that include a `blueprint.json` along with all the resources it references (plugins, themes, WXR files, etc.). Instead of hosting assets externally, bundle them alongside the blueprint.
|
|
300
|
+
|
|
301
|
+
### Bundle Structure
|
|
302
|
+
|
|
303
|
+
```
|
|
304
|
+
my-bundle/
|
|
305
|
+
├── blueprint.json ← must be at the root
|
|
306
|
+
├── my-plugin.zip ← zipped plugin directory
|
|
307
|
+
├── theme.zip
|
|
308
|
+
└── content/
|
|
309
|
+
└── sample-content.wxr
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
Plugins and themes must be zipped before bundling — `installPlugin` expects a zip, not a raw directory. To create the zip from a plugin directory:
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
cd my-bundle
|
|
316
|
+
zip -r my-plugin.zip my-plugin/
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Referencing Bundled Resources
|
|
320
|
+
|
|
321
|
+
Use the `bundled` resource type to reference files within the bundle:
|
|
322
|
+
|
|
323
|
+
```json
|
|
324
|
+
{
|
|
325
|
+
"step": "installPlugin",
|
|
326
|
+
"pluginData": {
|
|
327
|
+
"resource": "bundled",
|
|
328
|
+
"path": "/my-plugin.zip"
|
|
329
|
+
},
|
|
330
|
+
"options": { "activate": true }
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
```json
|
|
335
|
+
{
|
|
336
|
+
"step": "importWxr",
|
|
337
|
+
"file": {
|
|
338
|
+
"resource": "bundled",
|
|
339
|
+
"path": "/content/sample-content.wxr"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
### Creating a Bundle Step by Step
|
|
345
|
+
|
|
346
|
+
1. Create the bundle directory and add `blueprint.json` at its root.
|
|
347
|
+
2. Write your plugin/theme source files in a subdirectory (e.g. `my-plugin/my-plugin.php`).
|
|
348
|
+
3. Zip the plugin directory: `zip -r my-plugin.zip my-plugin/`
|
|
349
|
+
4. Reference it in `blueprint.json` using `{ "resource": "bundled", "path": "/my-plugin.zip" }`.
|
|
350
|
+
|
|
351
|
+
Full example — a bundle that installs a custom plugin:
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
dashboard-widget-bundle/
|
|
355
|
+
├── blueprint.json
|
|
356
|
+
├── dashboard-widget.zip ← zip of dashboard-widget/
|
|
357
|
+
└── dashboard-widget/ ← plugin source (kept for editing)
|
|
358
|
+
└── dashboard-widget.php
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
```json
|
|
362
|
+
{
|
|
363
|
+
"$schema": "https://playground.wordpress.net/blueprint-schema.json",
|
|
364
|
+
"landingPage": "/wp-admin/",
|
|
365
|
+
"preferredVersions": { "php": "8.3", "wp": "latest" },
|
|
366
|
+
"steps": [
|
|
367
|
+
{ "step": "login" },
|
|
368
|
+
{
|
|
369
|
+
"step": "installPlugin",
|
|
370
|
+
"pluginData": { "resource": "bundled", "path": "/dashboard-widget.zip" },
|
|
371
|
+
"options": { "activate": true }
|
|
372
|
+
}
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Distribution Formats
|
|
378
|
+
|
|
379
|
+
| Format | How to use |
|
|
380
|
+
|--------|-----------|
|
|
381
|
+
| ZIP file (remote) | Website: `https://playground.wordpress.net/?blueprint-url=https://example.com/bundle.zip` |
|
|
382
|
+
| ZIP file (local) | CLI: `npx @wp-playground/cli server --blueprint=./bundle.zip` |
|
|
383
|
+
| Local directory | CLI: `npx @wp-playground/cli server --blueprint=./my-bundle/ --blueprint-may-read-adjacent-files` |
|
|
384
|
+
| Git repository directory | Point `blueprint-url` at a repo directory containing `blueprint.json` |
|
|
385
|
+
|
|
386
|
+
**GOTCHA:** Local directory bundles always need `--blueprint-may-read-adjacent-files` for the CLI to read bundled resources. Without it, any `"resource": "bundled"` reference will fail with a "File not found" error. ZIP bundles don't need this flag — all files are self-contained inside the archive.
|
|
387
|
+
|
|
388
|
+
## Testing Blueprints
|
|
389
|
+
|
|
390
|
+
### Inline Blueprints (quick test, no bundles)
|
|
391
|
+
|
|
392
|
+
Minify the blueprint JSON (no extra whitespace), prepend `https://playground.wordpress.net/#`, and open the URL in a browser:
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
https://playground.wordpress.net/#{"$schema":"https://playground.wordpress.net/blueprint-schema.json","preferredVersions":{"php":"8.3","wp":"latest"},"steps":[{"step":"login"}]}
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Very large blueprints may exceed browser URL length limits; use the CLI instead.
|
|
399
|
+
|
|
400
|
+
### Local CLI Testing
|
|
401
|
+
|
|
402
|
+
**Interactive server** (keeps running, opens in browser):
|
|
403
|
+
```bash
|
|
404
|
+
# Directory bundle — requires --blueprint-may-read-adjacent-files
|
|
405
|
+
npx @wp-playground/cli server --blueprint=./my-bundle/ --blueprint-may-read-adjacent-files
|
|
406
|
+
|
|
407
|
+
# ZIP bundle — self-contained, no extra flags needed
|
|
408
|
+
npx @wp-playground/cli server --blueprint=./bundle.zip
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
**Headless validation** (runs blueprint and exits):
|
|
412
|
+
```bash
|
|
413
|
+
npx @wp-playground/cli run-blueprint --blueprint=./my-bundle/ --blueprint-may-read-adjacent-files
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
### Testing with the wordpress-playground-server Skill
|
|
417
|
+
|
|
418
|
+
Use the `wordpress-playground-server` skill to start a local Playground instance with `--blueprint /path/to/blueprint.json`, then verify the expected state with Playwright MCP. For directory bundles, pass `--blueprint-may-read-adjacent-files` as an extra argument.
|
|
@@ -24,6 +24,8 @@ Use this skill when the task involves:
|
|
|
24
24
|
|
|
25
25
|
## Procedure
|
|
26
26
|
|
|
27
|
+
Before deciding what to register, read `references/domain-vs-projection.md` — abilities live at the domain capability layer; MCP / Command Palette / REST exposure is a projection. Registration shape and exposure shape are different decisions, and conflating them forces re-registration every time a consumer's constraints change.
|
|
28
|
+
|
|
27
29
|
### 1) Confirm availability and version constraints
|
|
28
30
|
|
|
29
31
|
- If this is WP core work, check `signals.isWpCoreCheckout` and `versions.wordpress.core`.
|
|
@@ -48,6 +50,14 @@ If you need a logical grouping, register an ability category early (see `referen
|
|
|
48
50
|
|
|
49
51
|
### 4) Register abilities (PHP)
|
|
50
52
|
|
|
53
|
+
For grouping decisions (how many abilities to register, and where to put filters vs. new ability names), read `references/grouping-heuristic.md` first — it keeps you from shipping one atomic ability per REST operation.
|
|
54
|
+
|
|
55
|
+
To avoid drift between the ability and the existing UI / REST code path, see `references/shared-core-service.md` — abilities, REST handlers, CLI commands, and UI controllers should be thin adapters over a shared service. The reference also covers the metric trap (REST handlers that emit usage telemetry) and the `AGENTS.md` rule for keeping registrations in sync when underlying code paths change.
|
|
56
|
+
|
|
57
|
+
For shared helper patterns when multiple execute callbacks delegate to existing REST controllers, see `references/plugin-family-patterns.md` (identify the shared-API-client vs zero-arg-controllers shape) and `references/delegate-helper-pattern.md` (one helper shape that works, and when not to use it).
|
|
58
|
+
|
|
59
|
+
For standardized `WP_Error` codes that let agents reason about retry vs. escalation, see `references/error-code-vocabulary.md`.
|
|
60
|
+
|
|
51
61
|
Implement the ability in PHP registration with:
|
|
52
62
|
|
|
53
63
|
- stable `id` (namespaced),
|
|
@@ -87,6 +97,8 @@ Use the documented init hooks for Abilities API registration so they load at the
|
|
|
87
97
|
- wrong REST base/namespace,
|
|
88
98
|
- JS dependency not bundled,
|
|
89
99
|
- caching (object/page caches) masking changes.
|
|
100
|
+
- Execute callback returns unexpected errors or silently ignores input:
|
|
101
|
+
- `input_schema` defaults aren't being applied, pagination key drift between the ability and the backing, or `empty()`-based ID validation — see `references/input-schema-gotchas.md`.
|
|
90
102
|
|
|
91
103
|
## Escalation
|
|
92
104
|
|