wordpress-agent-kit 0.4.0 → 0.5.1

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.
Files changed (132) hide show
  1. package/.agents/skills/blueprint/SKILL.md +418 -0
  2. package/.agents/skills/wordpress-router/SKILL.md +52 -0
  3. package/.agents/skills/wordpress-router/references/decision-tree.md +55 -0
  4. package/.agents/skills/wp-abilities-api/SKILL.md +108 -0
  5. package/.agents/skills/wp-abilities-api/references/delegate-helper-pattern.md +241 -0
  6. package/.agents/skills/wp-abilities-api/references/domain-vs-projection.md +113 -0
  7. package/.agents/skills/wp-abilities-api/references/error-code-vocabulary.md +123 -0
  8. package/.agents/skills/wp-abilities-api/references/grouping-heuristic.md +89 -0
  9. package/.agents/skills/wp-abilities-api/references/input-schema-gotchas.md +265 -0
  10. package/.agents/skills/wp-abilities-api/references/php-registration.md +94 -0
  11. package/.agents/skills/wp-abilities-api/references/plugin-family-patterns.md +233 -0
  12. package/.agents/skills/wp-abilities-api/references/rest-api.md +13 -0
  13. package/.agents/skills/wp-abilities-api/references/shared-core-service.md +184 -0
  14. package/.agents/skills/wp-abilities-audit/SKILL.md +199 -0
  15. package/.agents/skills/wp-abilities-audit/references/audit-schema.md +300 -0
  16. package/.agents/skills/wp-abilities-audit/references/capability-gate-tracing.md +197 -0
  17. package/.agents/skills/wp-abilities-audit/references/controller-enumeration.md +116 -0
  18. package/.agents/skills/wp-abilities-verify/SKILL.md +215 -0
  19. package/.agents/skills/wp-abilities-verify/references/annotation-correctness.md +154 -0
  20. package/.agents/skills/wp-abilities-verify/references/audit-schema-validation.md +131 -0
  21. package/.agents/skills/wp-abilities-verify/references/permission-roundtrip.md +190 -0
  22. package/.agents/skills/wp-abilities-verify/references/runtime-harness.md +462 -0
  23. package/.agents/skills/wp-abilities-verify/references/schema-lints.md +118 -0
  24. package/.agents/skills/wp-abilities-verify/references/static-enumeration.md +126 -0
  25. package/.agents/skills/wp-block-development/SKILL.md +175 -0
  26. package/.agents/skills/wp-block-development/references/attributes-and-serialization.md +22 -0
  27. package/.agents/skills/wp-block-development/references/block-json.md +49 -0
  28. package/.agents/skills/wp-block-development/references/creating-new-blocks.md +46 -0
  29. package/.agents/skills/wp-block-development/references/debugging.md +36 -0
  30. package/.agents/skills/wp-block-development/references/deprecations.md +24 -0
  31. package/.agents/skills/wp-block-development/references/dynamic-rendering.md +23 -0
  32. package/.agents/skills/wp-block-development/references/inner-blocks.md +25 -0
  33. package/.agents/skills/wp-block-development/references/registration.md +30 -0
  34. package/.agents/skills/wp-block-development/references/supports-and-wrappers.md +18 -0
  35. package/.agents/skills/wp-block-development/references/tooling-and-testing.md +21 -0
  36. package/.agents/skills/wp-block-development/scripts/list_blocks.mjs +121 -0
  37. package/.agents/skills/wp-block-themes/SKILL.md +117 -0
  38. package/.agents/skills/wp-block-themes/references/creating-new-block-theme.md +37 -0
  39. package/.agents/skills/wp-block-themes/references/debugging.md +24 -0
  40. package/.agents/skills/wp-block-themes/references/patterns.md +18 -0
  41. package/.agents/skills/wp-block-themes/references/style-variations.md +14 -0
  42. package/.agents/skills/wp-block-themes/references/templates-and-parts.md +16 -0
  43. package/.agents/skills/wp-block-themes/references/theme-json.md +59 -0
  44. package/.agents/skills/wp-block-themes/scripts/detect_block_themes.mjs +117 -0
  45. package/.agents/skills/wp-interactivity-api/SKILL.md +180 -0
  46. package/.agents/skills/wp-interactivity-api/references/debugging.md +29 -0
  47. package/.agents/skills/wp-interactivity-api/references/directives-quickref.md +30 -0
  48. package/.agents/skills/wp-interactivity-api/references/server-side-rendering.md +310 -0
  49. package/.agents/skills/wp-performance/SKILL.md +147 -0
  50. package/.agents/skills/wp-performance/references/autoload-options.md +24 -0
  51. package/.agents/skills/wp-performance/references/cron.md +20 -0
  52. package/.agents/skills/wp-performance/references/database.md +20 -0
  53. package/.agents/skills/wp-performance/references/http-api.md +15 -0
  54. package/.agents/skills/wp-performance/references/measurement.md +21 -0
  55. package/.agents/skills/wp-performance/references/object-cache.md +24 -0
  56. package/.agents/skills/wp-performance/references/query-monitor-headless.md +38 -0
  57. package/.agents/skills/wp-performance/references/server-timing.md +22 -0
  58. package/.agents/skills/wp-performance/references/wp-cli-doctor.md +24 -0
  59. package/.agents/skills/wp-performance/references/wp-cli-profile.md +32 -0
  60. package/.agents/skills/wp-performance/scripts/perf_inspect.mjs +128 -0
  61. package/.agents/skills/wp-phpstan/SKILL.md +98 -0
  62. package/.agents/skills/wp-phpstan/references/configuration.md +52 -0
  63. package/.agents/skills/wp-phpstan/references/third-party-classes.md +76 -0
  64. package/.agents/skills/wp-phpstan/references/wordpress-annotations.md +124 -0
  65. package/.agents/skills/wp-phpstan/scripts/phpstan_inspect.mjs +263 -0
  66. package/.agents/skills/wp-playground/SKILL.md +233 -0
  67. package/.agents/skills/wp-playground/references/blueprints.md +36 -0
  68. package/.agents/skills/wp-playground/references/cli-commands.md +39 -0
  69. package/.agents/skills/wp-playground/references/debugging.md +16 -0
  70. package/.agents/skills/wp-playground/references/e2e-playwright.md +115 -0
  71. package/.agents/skills/wp-plugin-development/SKILL.md +113 -0
  72. package/.agents/skills/wp-plugin-development/references/data-and-cron.md +19 -0
  73. package/.agents/skills/wp-plugin-development/references/debugging.md +19 -0
  74. package/.agents/skills/wp-plugin-development/references/lifecycle.md +33 -0
  75. package/.agents/skills/wp-plugin-development/references/security.md +29 -0
  76. package/.agents/skills/wp-plugin-development/references/settings-api.md +22 -0
  77. package/.agents/skills/wp-plugin-development/references/structure.md +16 -0
  78. package/.agents/skills/wp-plugin-development/scripts/detect_plugins.mjs +122 -0
  79. package/.agents/skills/wp-plugin-directory-guidelines/SKILL.md +133 -0
  80. package/.agents/skills/wp-plugin-directory-guidelines/references/gpl-compliance.md +217 -0
  81. package/.agents/skills/wp-plugin-directory-guidelines/references/guideline-review-checklist.md +592 -0
  82. package/.agents/skills/wp-plugin-directory-guidelines/references/naming-rules.md +121 -0
  83. package/.agents/skills/wp-project-triage/SKILL.md +39 -0
  84. package/.agents/skills/wp-project-triage/references/triage.schema.json +143 -0
  85. package/.agents/skills/wp-project-triage/scripts/detect_wp_project.mjs +610 -0
  86. package/.agents/skills/wp-rest-api/SKILL.md +115 -0
  87. package/.agents/skills/wp-rest-api/references/authentication.md +18 -0
  88. package/.agents/skills/wp-rest-api/references/custom-content-types.md +20 -0
  89. package/.agents/skills/wp-rest-api/references/discovery-and-params.md +20 -0
  90. package/.agents/skills/wp-rest-api/references/responses-and-fields.md +30 -0
  91. package/.agents/skills/wp-rest-api/references/routes-and-endpoints.md +36 -0
  92. package/.agents/skills/wp-rest-api/references/schema.md +22 -0
  93. package/.agents/skills/wp-wpcli-and-ops/SKILL.md +126 -0
  94. package/.agents/skills/wp-wpcli-and-ops/references/automation.md +30 -0
  95. package/.agents/skills/wp-wpcli-and-ops/references/cron-and-cache.md +23 -0
  96. package/.agents/skills/wp-wpcli-and-ops/references/debugging.md +17 -0
  97. package/.agents/skills/wp-wpcli-and-ops/references/multisite.md +22 -0
  98. package/.agents/skills/wp-wpcli-and-ops/references/packages-and-updates.md +22 -0
  99. package/.agents/skills/wp-wpcli-and-ops/references/safety.md +30 -0
  100. package/.agents/skills/wp-wpcli-and-ops/references/search-replace.md +40 -0
  101. package/.agents/skills/wp-wpcli-and-ops/scripts/wpcli_inspect.mjs +90 -0
  102. package/.agents/skills/wp-wpengine/SKILL.md +398 -0
  103. package/.agents/skills/wp-wpengine/references/ci-gate.md +469 -0
  104. package/.agents/skills/wp-wpengine/references/github-actions-deploy.md +736 -0
  105. package/.agents/skills/wp-wpengine/scripts/ci-gate.sh +118 -0
  106. package/.agents/skills/wp-wpengine/scripts/wpe-check.sh +89 -0
  107. package/.agents/skills/wp-wpengine/scripts/wpe-preflight.sh +104 -0
  108. package/.agents/skills/wpds/SKILL.md +59 -0
  109. package/.github/agents/wp-architect.agent.md +1 -2
  110. package/.github/copilot-instructions.md +1 -1
  111. package/.github/instructions/wordpress-workflow.instructions.md +3 -3
  112. package/AGENTS.md +22 -10
  113. package/AGENTS.template.md +20 -10
  114. package/README.md +89 -85
  115. package/dist/cli.js +5 -1
  116. package/dist/commands/clean-skills.js +64 -0
  117. package/dist/commands/setup.js +6 -2
  118. package/dist/commands/sync-skills.js +3 -0
  119. package/dist/lib/api.js +164 -5
  120. package/dist/lib/installer.js +166 -2
  121. package/extensions/wp-agent-kit/index.ts +185 -10
  122. package/package.json +10 -14
  123. package/skills-custom/wp-wpengine/SKILL.md +299 -28
  124. package/skills-custom/wp-wpengine/references/ci-gate.md +469 -0
  125. package/skills-custom/wp-wpengine/references/github-actions-deploy.md +736 -0
  126. package/skills-custom/wp-wpengine/scripts/ci-gate.sh +118 -0
  127. package/skills-custom/wp-wpengine/scripts/wpe-check.sh +89 -0
  128. package/skills-custom/wp-wpengine/scripts/wpe-preflight.sh +104 -0
  129. package/.github/workflows/ci.yml +0 -44
  130. package/.husky/pre-commit +0 -7
  131. package/CLI_REVIEW.md +0 -250
  132. package/biome.json +0 -39
@@ -0,0 +1,469 @@
1
+ # CI Gate — Pre-deploy Verification
2
+
3
+ ## The core policy: CI is the canonical truth
4
+
5
+ `--no-verify` bypasses local git hooks. **It is forbidden on any branch that feeds a WP Engine deploy.**
6
+ The enforcement is two-layered so `--no-verify` has no real effect:
7
+
8
+ 1. **CI gate** — runs on every push to `develop`, `staging`, `main`. Re-runs every check hooks run.
9
+ Required status check. Broken code cannot merge regardless of what happened locally.
10
+ 2. **Deploy `verify` job** — first job in every deploy workflow. Deploys never start without it.
11
+
12
+ ---
13
+
14
+ ## Two gates: PHP and JS/TS
15
+
16
+ WordPress projects have two independent quality gates that run in **parallel**:
17
+
18
+ ```
19
+ push / PR
20
+ ├── php-gate → php -l → phpcs (WPCS) → phpstan
21
+ └── js-gate → biome ci → tsc --noEmit → vitest run
22
+ ↓ both must pass
23
+ merge allowed
24
+
25
+ deploy workflow
26
+ └── verify (reruns both gates) → backup → push → smoke test
27
+ ```
28
+
29
+ Both gates are **required status checks** on all protected branches. A failure in either blocks merge.
30
+
31
+ ---
32
+
33
+ ## `ci-gate.yml` — run on every push and PR
34
+
35
+ ```yaml
36
+ # .github/workflows/ci-gate.yml
37
+ name: CI Gate
38
+
39
+ on:
40
+ push:
41
+ branches: [develop, staging, main]
42
+ pull_request:
43
+ branches: [develop, staging, main]
44
+
45
+ concurrency:
46
+ group: ci-${{ github.ref }}-${{ github.workflow }}
47
+ cancel-in-progress: true
48
+
49
+ jobs:
50
+ # ── PHP gate ────────────────────────────────────────────────────────────────
51
+ php-gate:
52
+ name: PHP gate (syntax · WPCS · PHPStan)
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+
57
+ - uses: shivammathur/setup-php@v2
58
+ with:
59
+ php-version: '8.2'
60
+ tools: composer, phpcs, phpstan
61
+ coverage: none
62
+
63
+ - name: Install PHP dependencies
64
+ run: composer install --no-interaction --no-progress --quiet
65
+
66
+ - name: PHP syntax lint
67
+ run: |
68
+ find . -name '*.php' \
69
+ -not -path '*/vendor/*' \
70
+ -not -path '*/node_modules/*' \
71
+ | xargs -P4 php -l
72
+
73
+ - name: PHPCS — WordPress coding standards
74
+ run: composer run phpcs # defined in composer.json scripts
75
+
76
+ - name: PHPStan — static analysis
77
+ run: composer run phpstan
78
+
79
+ # ── JS / TS gate ─────────────────────────────────────────────────────────────
80
+ js-gate:
81
+ name: JS/TS gate (biome · tsc · vitest)
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - uses: actions/checkout@v4
85
+
86
+ - uses: actions/setup-node@v4
87
+ with:
88
+ node-version: '20'
89
+ cache: 'npm'
90
+
91
+ - name: Install dependencies
92
+ run: npm ci
93
+
94
+ - name: Biome — lint + format (CI strict mode)
95
+ run: npx biome ci .
96
+
97
+ - name: TypeScript — type check
98
+ run: npm run typecheck # or: npx tsc --noEmit
99
+
100
+ - name: Unit tests
101
+ run: npm test -- --run # Vitest; adjust for Jest
102
+
103
+ - name: Build assets
104
+ run: npm run build
105
+
106
+ # ── Gate summary ─────────────────────────────────────────────────────────────
107
+ gate-passed:
108
+ name: Gate passed
109
+ runs-on: ubuntu-latest
110
+ needs: [php-gate, js-gate]
111
+ steps:
112
+ - run: |
113
+ echo "✅ Both PHP and JS/TS gates passed."
114
+ echo " Code is verified clean regardless of --no-verify on local push."
115
+ ```
116
+
117
+ > **Branch protection**: require `gate-passed` (not the individual jobs) as the required status check.
118
+ > This way adding a new language gate later only requires updating `needs:` here, not branch rules.
119
+
120
+ ---
121
+
122
+ ## Deploy workflows — `needs: verify`
123
+
124
+ The `verify` job in each deploy workflow re-runs both gates inline. A deploy never starts
125
+ without them — even on `workflow_dispatch` or an emergency force push.
126
+
127
+ ```yaml
128
+ jobs:
129
+ # ── Verify (mirrors both CI gates) ──────────────────────────────────────────
130
+ verify:
131
+ name: Verify — PHP + JS/TS (no-verify cannot skip this)
132
+ runs-on: ubuntu-latest
133
+ steps:
134
+ - uses: actions/checkout@v4
135
+
136
+ # PHP
137
+ - uses: shivammathur/setup-php@v2
138
+ with: { php-version: '8.2', tools: composer }
139
+ - run: composer install --no-interaction --quiet
140
+ - run: find . -name '*.php' -not -path '*/vendor/*' | xargs -P4 php -l
141
+ - run: composer run phpcs
142
+ - run: composer run phpstan
143
+
144
+ # JS/TS
145
+ - uses: actions/setup-node@v4
146
+ with: { node-version: '20', cache: 'npm' }
147
+ - run: npm ci
148
+ - run: npx biome ci .
149
+ - run: npm run typecheck
150
+ - run: npm test -- --run
151
+ - run: npm run build
152
+
153
+ # ── Actual deploy (never runs without verify) ────────────────────────────────
154
+ deploy:
155
+ needs: verify
156
+ ...
157
+ ```
158
+
159
+ ---
160
+
161
+ ## Git hooks setup
162
+
163
+ Hooks are the **developer feedback loop**. CI gate is the **enforcer**.
164
+ Both must exist and mirror each other.
165
+
166
+ ### `.githooks/pre-push` — no Husky dependency (works for PHP-heavy projects)
167
+
168
+ ```bash
169
+ #!/usr/bin/env bash
170
+ # .githooks/pre-push
171
+ # Activate: git config core.hooksPath .githooks
172
+ # (or: npm run prepare if package.json has a prepare script for this)
173
+ set -uo pipefail
174
+ root="$(git rev-parse --show-toplevel)"
175
+ cd "$root"
176
+
177
+ fail() { echo "✗ pre-push blocked: $1" >&2; echo " Fix it, then re-push. (CI will also catch it.)" >&2; exit 1; }
178
+
179
+ # ── PHP gate ──────────────────────────────────────────────────────────────────
180
+ if command -v composer >/dev/null && [ -x vendor/bin/phpcs ]; then
181
+ echo "→ php -l"
182
+ git ls-files '*.php' | xargs -P4 php -l >/dev/null || fail "PHP syntax error"
183
+
184
+ echo "→ phpcs"
185
+ composer run phpcs --quiet || fail "phpcs violations"
186
+
187
+ echo "→ phpstan"
188
+ composer run phpstan --quiet || fail "phpstan errors"
189
+ echo "✓ PHP gate green"
190
+ else
191
+ echo "⚠ composer/phpcs not installed — run 'composer install'. Skipping PHP gate."
192
+ fi
193
+
194
+ # ── JS/TS gate ────────────────────────────────────────────────────────────────
195
+ if [ -x node_modules/.bin/biome ]; then
196
+ echo "→ biome check"
197
+ npx biome check . --quiet || fail "biome lint/format issues (run: npx biome check --write .)"
198
+ echo "✓ JS/TS gate green"
199
+ else
200
+ echo "⚠ biome not installed — run 'npm install'. Skipping JS gate."
201
+ fi
202
+ ```
203
+
204
+ Activate once per clone:
205
+
206
+ ```bash
207
+ git config core.hooksPath .githooks
208
+ chmod +x .githooks/pre-push
209
+ ```
210
+
211
+ Or add to `package.json`:
212
+
213
+ ```json
214
+ "scripts": {
215
+ "prepare": "git config core.hooksPath .githooks 2>/dev/null || true"
216
+ }
217
+ ```
218
+
219
+ ---
220
+
221
+ ## Agent-runnable scripts
222
+
223
+ Place these in `.githooks/` or a `scripts/` directory so agents can run them directly.
224
+
225
+ ### `scripts/ci-gate.sh` — run the full CI gate locally
226
+
227
+ Agents can run this before recommending a push. It mirrors both CI jobs exactly.
228
+
229
+ ```bash
230
+ #!/usr/bin/env bash
231
+ # scripts/ci-gate.sh — run the full CI gate locally before pushing.
232
+ # Usage: bash scripts/ci-gate.sh [--php-only] [--js-only]
233
+ set -euo pipefail
234
+ root="$(git rev-parse --show-toplevel)"
235
+ cd "$root"
236
+
237
+ PHP_ONLY=false; JS_ONLY=false
238
+ for arg in "$@"; do
239
+ [[ "$arg" == "--php-only" ]] && PHP_ONLY=true
240
+ [[ "$arg" == "--js-only" ]] && JS_ONLY=true
241
+ done
242
+
243
+ PASS=0; FAIL=0
244
+ run() {
245
+ echo "▶ $*"
246
+ if "$@"; then echo " ✓"; ((PASS++)) ; else echo " ✗ FAILED"; ((FAIL++)); fi
247
+ }
248
+
249
+ if ! $JS_ONLY; then
250
+ echo "── PHP gate ──────────────────────────────────────────────────"
251
+ if command -v composer >/dev/null && [ -x vendor/bin/phpcs ]; then
252
+ run bash -c "git ls-files '*.php' | xargs -P4 php -l >/dev/null"
253
+ run composer run phpcs
254
+ run composer run phpstan
255
+ else
256
+ echo "⚠ composer not installed — skipping PHP gate"
257
+ fi
258
+ fi
259
+
260
+ if ! $PHP_ONLY; then
261
+ echo "── JS/TS gate ────────────────────────────────────────────────"
262
+ if [ -d node_modules ]; then
263
+ run npx biome check .
264
+ run npm run typecheck 2>/dev/null || run npx tsc --noEmit
265
+ run npm test -- --run
266
+ run npm run build
267
+ else
268
+ echo "⚠ node_modules missing — run 'npm install' first"
269
+ fi
270
+ fi
271
+
272
+ echo ""
273
+ echo "── Result ────────────────────────────────────────────────────"
274
+ echo " Passed: $PASS | Failed: $FAIL"
275
+ [[ "$FAIL" -eq 0 ]] && echo "✅ Gate green — safe to push" && exit 0
276
+ echo "❌ Gate failed — fix issues before pushing" && exit 1
277
+ ```
278
+
279
+ ### `scripts/wpe-preflight.sh` — pre-deploy checklist
280
+
281
+ Agents run this before triggering any WP Engine deploy. Checks SSH access, WP-CLI, and site health.
282
+
283
+ ```bash
284
+ #!/usr/bin/env bash
285
+ # scripts/wpe-preflight.sh — pre-deploy checklist for WP Engine.
286
+ # Usage: INSTALL=mysite bash scripts/wpe-preflight.sh [staging|production]
287
+ set -euo pipefail
288
+
289
+ ENV="${1:-production}"
290
+ INSTALL="${WPE_INSTALL:-${INSTALL:-}}"
291
+
292
+ [ -z "$INSTALL" ] && { echo "❌ Set INSTALL= or WPE_INSTALL= to the WP Engine install slug"; exit 1; }
293
+
294
+ SSH_HOST="${INSTALL}.ssh.wpengine.net"
295
+ FAIL=0
296
+ check() { echo "▶ $1"; shift; if "$@" 2>&1 | tail -1; then echo " ✓"; else echo " ✗ FAILED"; FAIL=1; fi; }
297
+
298
+ echo "── WP Engine preflight: ${INSTALL} (${ENV}) ───────────────────"
299
+
300
+ # SSH connectivity
301
+ check "SSH gateway reachable" \
302
+ ssh -o BatchMode=yes -o ConnectTimeout=10 \
303
+ -o StrictHostKeyChecking=accept-new \
304
+ "${INSTALL}@${SSH_HOST}" wp --info
305
+
306
+ # WordPress core version
307
+ check "WP core version" \
308
+ ssh "${INSTALL}@${SSH_HOST}" wp core version --skip-plugins --skip-themes
309
+
310
+ # Site URL sanity
311
+ check "siteurl + home match" bash -c "
312
+ SITEURL=\$(ssh ${INSTALL}@${SSH_HOST} wp option get siteurl --skip-plugins --skip-themes)
313
+ HOME=\$(ssh ${INSTALL}@${SSH_HOST} wp option get home --skip-plugins --skip-themes)
314
+ echo \"siteurl: \$SITEURL\"
315
+ echo \"home: \$HOME\"
316
+ [[ \"\$SITEURL\" == \"\$HOME\" ]]
317
+ "
318
+
319
+ # No PHP fatal errors on homepage
320
+ check "Homepage returns HTTP 2xx/3xx" bash -c "
321
+ URL=\$(ssh ${INSTALL}@${SSH_HOST} wp option get home --skip-plugins --skip-themes)
322
+ STATUS=\$(curl -s -o /dev/null -w '%{http_code}' -L --max-time 15 \"\$URL\")
323
+ echo \"HTTP \$STATUS\"
324
+ [[ \"\$STATUS\" -ge 200 && \"\$STATUS\" -lt 400 ]]
325
+ "
326
+
327
+ # Active plugin count (sanity — shouldn't be 0)
328
+ check "Active plugins present" bash -c "
329
+ COUNT=\$(ssh ${INSTALL}@${SSH_HOST} wp plugin list --status=active --format=count --skip-plugins --skip-themes)
330
+ echo \"\$COUNT active plugins\"
331
+ [[ \"\$COUNT\" -gt 0 ]]
332
+ "
333
+
334
+ echo ""
335
+ echo "── Preflight result ──────────────────────────────────────────"
336
+ [[ "$FAIL" -eq 0 ]] && echo "✅ All checks passed — safe to deploy" && exit 0
337
+ echo "❌ Preflight failed — do not deploy until issues are resolved" && exit 1
338
+ ```
339
+
340
+ ### `scripts/wpe-check.sh` — SSH connectivity diagnostic
341
+
342
+ Quick check for every configured WP Engine environment. Agents run this when debugging SSH issues.
343
+
344
+ ```bash
345
+ #!/usr/bin/env bash
346
+ # scripts/wpe-check.sh — verify SSH access to WP Engine environments.
347
+ # Usage: bash scripts/wpe-check.sh
348
+ # Reads installs from wp-cli.yml aliases or INSTALLS env var.
349
+ set -uo pipefail
350
+
351
+ # ── Discover installs from wp-cli.yml @aliases ──────────────────────────────
352
+ INSTALLS=()
353
+ if [ -f wp-cli.yml ]; then
354
+ while IFS= read -r line; do
355
+ # Lines like "@production:" → extract alias, then look for ssh: field
356
+ if [[ "$line" =~ ^@([a-zA-Z0-9_-]+): ]]; then
357
+ CURRENT_ALIAS="${BASH_REMATCH[1]}"
358
+ elif [[ "$line" =~ ^[[:space:]]+ssh:[[:space:]]+([^@]+)@ ]]; then
359
+ INSTALL="${BASH_REMATCH[1]}"
360
+ INSTALLS+=("$INSTALL:$CURRENT_ALIAS")
361
+ fi
362
+ done < wp-cli.yml
363
+ fi
364
+
365
+ # Fallback: check INSTALLS env var (space-separated slugs)
366
+ if [ ${#INSTALLS[@]} -eq 0 ] && [ -n "${WPE_INSTALLS:-}" ]; then
367
+ for slug in $WPE_INSTALLS; do
368
+ INSTALLS+=("$slug:$slug")
369
+ done
370
+ fi
371
+
372
+ [ ${#INSTALLS[@]} -eq 0 ] && {
373
+ echo "No installs found. Add @aliases with 'ssh:' to wp-cli.yml or set WPE_INSTALLS='slug1 slug2'"
374
+ exit 1
375
+ }
376
+
377
+ echo "── WP Engine SSH connectivity check ──────────────────────────"
378
+ PASS=0; FAIL=0
379
+
380
+ for entry in "${INSTALLS[@]}"; do
381
+ INSTALL="${entry%%:*}"
382
+ ALIAS="${entry##*:}"
383
+ SSH_HOST="${INSTALL}.ssh.wpengine.net"
384
+ printf " %-20s (%s) ... " "$INSTALL" "@$ALIAS"
385
+
386
+ if ssh -o BatchMode=yes -o ConnectTimeout=8 \
387
+ -o StrictHostKeyChecking=accept-new \
388
+ "${INSTALL}@${SSH_HOST}" wp core version \
389
+ --skip-plugins --skip-themes 2>/dev/null; then
390
+ echo "✓"
391
+ ((PASS++))
392
+ else
393
+ echo "✗ — check key at ~/.ssh/wpengine_ed25519 and portal SSH Keys"
394
+ ((FAIL++))
395
+ fi
396
+ done
397
+
398
+ echo ""
399
+ echo " $PASS connected | $FAIL failed"
400
+ [[ "$FAIL" -eq 0 ]] && exit 0 || exit 1
401
+ ```
402
+
403
+ ---
404
+
405
+ ## Branch protection
406
+
407
+ Configure in **GitHub → Settings → Branches**:
408
+
409
+ ### `develop`
410
+ ```
411
+ ✅ Require status checks: gate-passed
412
+ ✅ Require branches to be up to date
413
+ ```
414
+
415
+ ### `staging`
416
+ ```
417
+ ✅ Require pull request (1 reviewer)
418
+ ✅ Dismiss stale reviews on new commits
419
+ ✅ Require status checks: gate-passed
420
+ ✅ Require branches to be up to date
421
+ ✅ Do not allow bypassing the above settings
422
+ ```
423
+
424
+ ### `main`
425
+ ```
426
+ ✅ Require pull request (2 reviewers)
427
+ ✅ Dismiss stale reviews on new commits
428
+ ✅ Require status checks: gate-passed, staging-source-check
429
+ ✅ Require branches to be up to date
430
+ ✅ Do not allow force pushes
431
+ ✅ Do not allow deletions
432
+ ✅ Do not allow bypassing the above settings ← admins cannot override
433
+ ```
434
+
435
+ > Use `gate-passed` (the summary job), not `php-gate` / `js-gate` individually.
436
+ > Branch protection rule names are matched by job name — if you rename a job, update the rule.
437
+
438
+ ---
439
+
440
+ ## What `--no-verify` bypasses (and what it doesn't)
441
+
442
+ | Check | `--no-verify` | CI gate | Deploy `verify` job |
443
+ |---|---|---|---|
444
+ | pre-commit hook | ❌ skipped | ✅ runs | ✅ runs |
445
+ | pre-push hook | ❌ skipped | ✅ runs | ✅ runs |
446
+ | `gate-passed` status check | ✅ runs | ✅ runs | ✅ runs |
447
+ | Branch protection | ✅ blocks | ✅ blocks | ✅ blocks |
448
+ | Deploy starts | — | — | ✅ blocked until verify passes |
449
+
450
+ **Result:** `--no-verify` only removes the developer's fast local feedback loop.
451
+ Every check still runs in CI and in the deploy workflow. The only consequence is
452
+ slower feedback — not a path to deploying broken code.
453
+
454
+ ---
455
+
456
+ ## Project type matrix
457
+
458
+ Adjust which gates run based on the project (from `wp-project-triage` output):
459
+
460
+ | Project type | PHP gate | JS/TS gate | Build step |
461
+ |---|---|---|---|
462
+ | Classic plugin (PHP only) | ✅ | ❌ | ❌ |
463
+ | Block plugin (PHP + JS) | ✅ | ✅ | ✅ `npm run build` |
464
+ | Block theme | ✅ | ✅ | ✅ `npm run build` |
465
+ | Headless / full JS | ❌ | ✅ | ✅ `npm run build` |
466
+ | Monorepo (wp-agent-os style) | ✅ | ✅ per package | ✅ per package |
467
+
468
+ For PHP-only projects, remove the `js-gate` job from `ci-gate.yml` and the JS section from the `verify` job.
469
+ The `gate-passed` job only needs to reference `needs: [php-gate]`.