PluginProbe
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF / trunk
Imagify Image Optimization: Optimize Images | Compress & Convert to WebP/AVIF vtrunk
2.3.4 2.3.3 2.3.2 2.3.1 2.3.0 2.2.9 2.2.8 trunk 1.10 1.3.3 1.3.4 1.3.5 1.3.5.1 1.3.5.2 1.3.6 1.3.6.1 1.4 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.5 All 103 releases
← All changes | AGENTS.md +107 -265 2.2.8 → trunk View file →
@@ -1,321 +1,157 @@
1 -# Imagify – AI Coding & Architecture Guidelines
1 +# Imagify — project instructions for AI agents
2 2
3 -This file defines NON-NEGOTIABLE rules for any AI-assisted work
4 -(Claude Code, ChatGPT, JetBrains AI Assistant, Cursor, etc.)
5 -in this repository.
3 +Project Configuration values below override a pipeline's derived defaults. Behaviour — how agents
4 +run, dispatch, or report — belongs to the pipeline, not to this file.
6 5
7 -Skills define behavioral guidance.
8 -AGENTS.md defines mandatory guardrails.
9 -If a conflict exists, AGENTS.md prevails.
10 -
11 -The objective is to keep Imagify:
12 -
13 -- WordPress.org compliant
14 -- Architecturally consistent
15 -- Secure
16 -- Maintainable
17 -- Review-friendly
18 -
19 -This document applies to ALL automated or AI-generated changes.
20 -
21 6 ---
22 7
23 -# 1. Project Overview
8 +## Project Configuration
24 9
25 -Imagify is a single-edition WordPress plugin for image optimization.
10 +| Variable | Value |
11 +|---|---|
12 +| `REPO` | `wp-media/imagify-plugin` |
13 +| `SLUG` / `TEXT_DOMAIN` | `imagify` |
14 +| `BASE_BRANCH` | `develop` |
15 +| Protected branches | `develop`, `master` — never commit directly |
16 +| Branch naming | `<prefix>/<issue>-<slug>`; prefix `fix` (bugs), `enhancement` (features, incl. `feat` commits), `test` |
17 +| Test (full / unit / integration) | `composer run-tests` / `composer test-unit` / `composer test-integration` |
18 +| Test (one group) | `vendor/bin/phpunit --configuration Tests/Integration/phpunit.xml.dist --group <Name>` |
19 +| Lint / auto-fix | `composer phpcs` / `composer phpcbf` |
20 +| Static analysis | `composer run-stan` |
21 +| Build frontend | `npm run build` |
22 +| Local env up / down / seed | `bash bin/dev-up.sh` / `bash bin/dev-down.sh` / `bash bin/dev-seed.sh` |
23 +| E2E runner | `bash bin/test-e2e.sh` (`--headed`, `--ui`, or a spec path) |
24 +| Local URL | `http://localhost:8888` — admin `admin` / `password` |
25 +| Settings page | `/wp-admin/options-general.php?page=imagify` |
26 +| Key option | `imagify_settings` (API key + config) |
27 +| PR template | `.github/PULL_REQUEST_TEMPLATE.md` |
26 28
27 -- **Repo:** `wp-media/imagify-plugin`
28 -- **Plugin slug:** `imagify`
29 -- **PHP namespace root:** `Imagify\`
30 -- **PSR-4 root:** `classes/`
29 +`.env.local` at the repo root (gitignored) holds `IMAGIFY_TESTS_API_KEY=<key>`. The same value must
30 +exist as a GitHub secret for CI optimization tests.
31 31
32 -There is no FREE/PRO split. The codebase has two layers:
33 -
34 -- `classes/` — modern PSR-4 code, namespace `Imagify\`, `declare(strict_types=1)` required. **New features go here.**
35 -- `inc/classes/` — legacy classmap code, `Imagify_` prefix. **Do not add new classes here; migrate out instead.**
36 -
37 -When modifying architecture:
38 -- Prefer the modern `classes/` layer for all new work.
39 -- Follow service provider + subscriber pattern for wiring.
40 -
41 32 ---
42 33
43 -# 2. Technology Stack
34 +## Traps
44 35
45 -- PHP 7.3+ (strict types, PSR-4 autoloading via Composer)
46 -- WordPress plugin APIs (hooks, options, WP-CLI, AJAX)
47 -- League Container (DI container + service providers + event subscribers)
48 -- ActionScheduler (async background jobs)
49 -- Strauss (Composer dependency namespace prefixing → `Imagify\Dependencies\`)
50 -- JavaScript / Grunt (`_dev/` pipeline → `assets/`)
51 -- Playwright + TypeScript (E2E testing under `Tests/e2e/`)
36 +Things that fail in ways you will not notice.
52 37
38 +- **Run `composer install` before any test or lint command.** Strauss namespace-prefixing is a
39 + Composer post-install hook. Without it, PHPCS and PHPUnit cannot resolve `Imagify\Dependencies\*`
40 + and fail with misleading autoload errors.
41 +- **`WordPress.Security.NonceVerification.Missing` and `.Recommended` are deliberately suppressed**
42 + in `phpcs.xml`. Do not add `phpcs:ignore` for them and do not restructure code to satisfy them.
43 +- **`assets/` is build output.** Edit `_dev/` and rebuild, or the next build discards your work.
44 +- **There is no JavaScript unit test runner** (no Jest, no Vitest). Never invent `npm test`. Frontend
45 + verification is `npm run build` plus Playwright; otherwise report JS tests as `N/A`.
46 +- **Optimization behaviour sits behind license, API-key and quota guards.** Before reporting that a
47 + feature works or is broken, run `bash bin/dev-seed.sh` and confirm the key landed:
48 + `npx @wordpress/env run cli wp option get imagify_settings --format=json | grep -c '"api_key":"[^"]\+'`
49 + Only once the key is present (result `1`) may you treat a guard as a genuine blocker. Never report a
50 + behavioural pass or failure *through* a blocked guard — report "cannot verify" with the guard's
51 + `file:line`. Guard locations are in the `e2e` skill.
52 +- **A PR's number is not its issue number.** Read it back from the `gh pr create` output.
53 +- **PHP-rendered admin UI is a frontend change.** `wp_admin_notice()`,
54 + `add_action( 'admin_notices', ... )` and `add_settings_error()` need frontend scoping and testing
55 + despite living in PHP.
53 56
54 -# 3. Code Structure
55 -
56 -```
57 -classes/ New PHP code (PSR-4, Imagify\ namespace)
58 -inc/ Legacy PHP includes (procedural, no namespace)
59 -inc/classes/ Legacy class files migrating toward classes/
60 -assets/ Compiled frontend assets (do not edit directly)
61 -_dev/ Frontend source (JS, SCSS, Grunt config)
62 -views/ PHP view templates
63 -Tests/ PHPUnit tests
64 -Tests/e2e/ Playwright E2E tests (TypeScript)
65 -bin/ CLI scripts (dev-up, dev-down, dev-seed, test-e2e, build-knowledge-graph)
66 -docs/ Documentation (E2E_TESTING.md, etc.)
67 -.aiassistant/ Skill files for AI assistants
68 -.claude/agents/ Claude Code sub-agents (qa-engineer, e2e-qa-tester)
69 -```
70 -
71 57 ---
72 58
73 -# 4. Coding Standards & Static Analysis
59 +## Architecture
74 60
75 -Source of truth:
61 +Single-edition plugin — no FREE/PRO split. Namespace root `Imagify\`, PSR-4 root `classes/`.
76 62
77 -- Composer scripts (`composer.json`)
78 -- PHPCS ruleset (`phpcs.xml`)
79 -- PHPStan config (`phpstan.neon.dist`)
80 -- WordPress Plugin Check: https://github.com/WordPress/plugin-check/
81 -- CI pipeline rules
63 +- `classes/` — modern PSR-4, `declare(strict_types=1)` required. **New features go here.**
64 +- `inc/classes/` — legacy classmap, `Imagify_` prefix, migrating toward `classes/`. **Add nothing here.**
82 65
83 -Imagify must remain compatible with WordPress.org validation rules.
66 +In new `classes/` code:
84 67
85 -Any change affecting public APIs, output, security, metadata, or
86 -plugin bootstrap behavior must be evaluated against WordPress Plugin Check expectations.
68 +- No new singletons or `InstanceGetterTrait` usage. The trait is still used in `classes/Plugin.php`,
69 + `classes/Bulk/Bulk.php` and elsewhere — that is legacy precedent, not a pattern to copy.
70 +- No bare `add_action()` / `add_filter()`. Register hooks through a `Subscriber` implementing
71 + `SubscriberInterface`, listed in `ServiceProvider::get_subscribers()`.
72 +- Service providers live at `classes/*/ServiceProvider.php` and are registered in
73 + `config/providers.php`.
74 +- No global state, and no UI logic coupled to infrastructure logic. The legacy `inc/` layer is
75 + procedural and full of both — do not pattern-match from it.
87 76
88 -AI MUST:
77 +Nonce action naming: `imagify_<feature>_<action>`.
89 78
90 -- Read `composer.json` first and use the defined scripts (e.g. `phpcs`, `phpcbf`, `run-stan`, `test-unit`, `test-integration`) instead of inventing commands.
91 -- Auto-discover PHPCS configuration and follow it as the single source of truth.
79 +DI container is Strauss-prefixed: `Imagify\Dependencies\League\Container\Container` — a plain
80 +`use League\Container\Container;` is wrong here. Async work uses ActionScheduler, not wp-cron.
92 81
93 -## 4.1 Tooling Auto-Discovery (MANDATORY)
82 +Frontend source is `_dev/` (Grunt, `gruntfile.js`); `_dev/` also carries its own `bud.config.js`.
94 83
95 -Before making changes that affect standards or formatting, the agent MUST locate and respect the repository configuration files.
96 -
97 -### Required reads (in this order)
98 -1. `composer.json` — use scripts defined in `"scripts"` whenever possible; prefer the exact commands used by CI; do not invent lint/test commands.
99 -2. PHPCS ruleset (first match wins): `phpcs.xml`, `phpcs.xml.dist`
100 -3. Static analysis configs (if present): `phpstan.neon.dist`
101 -
102 -### Execution rules
103 -- Do NOT hardcode PHPCS standards.
104 -- Do NOT assume WordPress-Core or WordPress-Extra unless defined in the ruleset.
105 -
106 -If no PHPCS configuration exists, stop and ask.
107 -
108 84 ---
109 85
110 -# 5. Architectural Integrity
86 +## Coding standards
111 87
112 -AI must NOT:
88 +Source of truth: `composer.json` scripts, `phpcs.xml`, `phpstan.neon.dist`, CI. Never hardcode PHPCS
89 +standards or invent lint commands.
113 90
114 -- Introduce global state.
115 -- Add new singletons or `InstanceGetterTrait` usage in `classes/`.
116 -- Bypass dependency injection patterns used in the project.
117 -- Couple UI logic to infrastructure logic.
118 -- Add new classes to `inc/classes/`.
91 +Imagify must stay WordPress.org-compatible
92 +([Plugin Check](https://github.com/WordPress/plugin-check/)). Evaluate any change to public APIs,
93 +output, security, metadata, or bootstrap behaviour against it.
119 94
120 -Follow existing patterns:
95 +- PHP 7.4+, strict types in all new `classes/` files.
96 +- Text domain `imagify`: `esc_html__( 'Label', 'imagify' )`.
97 +- Authorization: use the project's registered capability (`'bulk-optimize'`, `'manage'`, …) in
98 + `current_user_can()`, never the coarse `manage_options`.
99 +- No jQuery in new or modified JavaScript — native DOM APIs only, no inline handlers, no unsafe
100 + `innerHTML`. Pass nonces via `wp_localize_script`.
101 +- Remote responses from the Imagify API are untrusted input and are this plugin's main attack
102 + surface. Validate and escape everything that comes back before storing or echoing it.
121 103
122 -- Service providers (`classes/*/ServiceProvider.php`)
123 -- Subscribers (`classes/*/Subscriber.php` implementing `SubscriberInterface`)
124 -- Container-based wiring (`config/providers.php`)
125 -- Strict types in all new `classes/` files
126 -
127 104 ---
128 105
129 -# 6. Testing & Validation
106 +## Testing
130 107
131 -For every change:
108 +Prefer **integration tests** (`Tests/Integration/`, annotated `@group FeatureName`) — they exercise
109 +real WordPress context, DI wiring and hook execution. Unit tests only for pure logic with no WP
110 +globals, container or hooks.
132 111
133 -1. Ensure no new PHPCS violations.
134 -2. Ensure static analysis still passes.
135 -3. Avoid altering unrelated test behavior.
136 -4. Do not delete tests unless clearly obsolete.
112 +Scale scope to risk: LOW = the relevant `--group`; MEDIUM = `composer test-unit` plus that group;
113 +HIGH = `composer run-tests`.
137 114
138 -If modifying templates:
139 -- Validate escaping correctness.
140 -- Ensure no functional regressions.
115 +Not scope violations: generated files (`*.min.js`, `*.min.css`), lockfiles, tests mirroring changed
116 +source, auto-formatter output.
141 117
142 118 ---
143 119
144 -# 7. E2E Testing
120 +## Commits and PRs
145 121
146 -Two Claude Code sub-agents in `.claude/agents/` support QA workflows:
122 +- Conventional Commits: `type(scope): short description`. Each commit passes PHPCS and static
123 + analysis before being made.
124 +- Pipeline-authored commits carry a `Co-Authored-By: <model> <[email protected]>` trailer so
125 + automated work stays auditable. Human-authored commits do not.
126 +- Do not squash unrelated changes. Do not amend commits already pushed.
127 +- Outside a pipeline working a specific ticket, only *suggest* commits — do not run `git commit` or
128 + `git push`.
129 +- PR title: `Closes #<N>: <short title>` — never a Conventional-Commit prefix; that is for commits.
130 +- The PR body needs a standalone `Closes #<N>` line, not buried in prose — that is what auto-closes.
131 +- Apply the `Made by AI` label to every AI-created PR and issue.
132 +- Split work vertically: each PR one complete behaviour including its tests. Never a backend PR plus
133 + a separate frontend PR for one feature, even when separate agents did the work.
134 +- Do not run large automated refactors or reorganize files without being asked. The legacy-to-modern
135 + migration is ongoing; "cleaning up while I'm here" is not in scope.
147 136
148 -| Agent | Use when |
149 -|-------|----------|
150 -| `qa-engineer` | Validating a PR against its ticket spec (strategy selection, test report) |
151 -| `e2e-qa-tester` | Driving the browser via Playwright, converting flows to spec files |
152 -
153 -Full E2E testing documentation: [`docs/E2E_TESTING.md`](docs/E2E_TESTING.md)
154 -
155 -The test directory is `Tests/e2e/` (capital T, consistent with the existing `Tests/` PHPUnit directory).
156 -
157 -The E2E suite runs in CI via `.github/workflows/e2e.yml`. The `IMAGIFY_TESTS_API_KEY` GitHub secret must be configured for optimization tests to run.
158 -
159 137 ---
160 138
161 -# 8. Local Development
139 +## On-demand references
162 140
163 -```bash
164 -# Start the local WordPress environment (Docker via wp-env)
165 -bash bin/dev-up.sh
141 +- **Browser testing** — admin URLs, page objects, environment variables, local running:
142 + [`docs/E2E_TESTING.md`](docs/E2E_TESTING.md)
143 +- **QA procedure** — tiers, spec conventions, guard locations: the `e2e` skill (`.claude/skills/e2e/`)
144 +- **Code structure** — use the installed pipeline's knowledge-graph skill if it provides one. A local
145 + builder also exists: `node bin/build-knowledge-graph.js` writes `.aiassistant/graph/` (gitignored).
146 + Do not mix the two graphs in one session; if neither is current, use grep rather than stopping.
166 147
167 -# Stop (preserves data) / full wipe
168 -bash bin/dev-down.sh
169 -bash bin/dev-down.sh --clean
170 -
171 -# Seed test data (idempotent)
172 -bash bin/dev-seed.sh
173 -
174 -# Run E2E tests locally (sources .env.local for API key automatically)
175 -bash bin/test-e2e.sh
176 -bash bin/test-e2e.sh --headed # watch the browser
177 -bash bin/test-e2e.sh --ui # Playwright interactive UI
178 -bash bin/test-e2e.sh specs/smoke # single spec
179 -```
180 -
181 -Create `.env.local` at the repo root (gitignored) with:
182 -```
183 -IMAGIFY_TESTS_API_KEY=your-key-here
184 -```
185 -
186 -- Site: `http://localhost:8888`
187 -- Admin: `http://localhost:8888/wp-admin` — `admin` / `password`
188 -
189 148 ---
190 149
191 -# 9. AI Working Protocol
150 +## Priority order
192 151
193 -AI must work in small, incremental changes.
152 +When these conflict, earlier wins:
194 153
195 -After each logical change set:
196 -- explain what changed
197 -- explain why
198 -- list potential edge cases
199 -
200 -AI must NOT:
201 -
202 -- Perform massive automated refactors without approval.
203 -- Reorganize files without explicit instruction.
204 -- Rewrite entire classes when a minimal fix is sufficient.
205 -
206 -## 9.1 Git Commit & Push Policy
207 -
208 -By default, AI may only **suggest** commit messages and must not run `git commit` or `git push`.
209 -
210 -**Exception — Issue Workflow:** When operating under the issue-workflow skill (triggered by `/task <number>`, `issue <number>`, or `#<number>`), the agent MAY:
211 -
212 -1. Run atomic `git commit` calls — one commit per logical, self-contained change set.
213 -2. Run `git push` exactly once after all commits are ready, to publish the branch.
214 -3. Create a GitHub Pull Request using the prepared PR draft.
215 -4. Monitor PR CI status checks until all pass or a failure is detected.
216 -
217 -Atomic commit rules:
218 -- Each commit must pass PHPCS and static analysis before being committed.
219 -- Commit message format: `type(scope): short description` (Conventional Commits).
220 -- No `Co-Authored-By` lines in commits.
221 -- Do not squash unrelated changes into a single commit.
222 -- Do not amend commits that have already been pushed.
223 -
224 -
225 -# 10. PR Hygiene
226 -
227 -Changes must:
228 -
229 -- Be minimal and scoped.
230 -- Have clear intent.
231 -- Avoid noise in diff.
232 -- Avoid unrelated formatting changes.
233 -
234 -
235 -# 11. Security First
236 -
237 -Always assume:
238 -
239 -- User input is untrusted.
240 -- Remote API responses are untrusted.
241 -- Stored values may be tampered with.
242 -
243 -Never:
244 -
245 -- Store sensitive values in plain text without review.
246 -- Introduce unsafe serialization.
247 -- Echo unescaped dynamic data.
248 -
249 -
250 -# 12. When in Doubt
251 -
252 -Stop.
253 -Explain the ambiguity.
254 -Ask for clarification.
255 -
256 -Architectural integrity is more important than speed.
257 -
258 -
259 -# 13. Sub-Agents
260 -
261 -Reusable specialist agents live in `.aiassistant/agents/`. Claude Code discovers them via the `.claude/agents` symlink; other tools can read them directly from `.aiassistant/agents/`.
262 -
263 -| Agent | File | Invoke when |
264 -|-------|------|-------------|
265 -| `qa-engineer` | `.aiassistant/agents/qa-engineer.md` | Validating a PR against its ticket spec — reads acceptance criteria, runs functional/browser/analysis strategies, produces a structured test report |
266 -| `e2e-qa-tester` | `.aiassistant/agents/e2e-qa-tester.md` | Driving the browser via Playwright, walking through "How to test" steps, converting validated flows into Playwright spec files under `Tests/e2e/` |
267 -
268 -The `qa-engineer` agent delegates browser flows to `e2e-qa-tester` automatically when the change involves admin UI.
269 -
270 -
271 -# 14. Skills Activation
272 -
273 -The repository defines AI Skills under `.aiassistant/skills/`.
274 -
275 -Agents MUST activate the relevant skill depending on the task:
276 -
277 -| Task | Skill |
278 -|------|-------|
279 -| Template or UI changes | WordPress Compliance |
280 -| Structural or architectural changes | Imagify Architecture |
281 -| Service modifications | Both skills |
282 -| Codebase exploration / dependency tracing | Knowledge Graph |
283 -| Working on a GitHub issue | Issue Workflow |
284 -
285 -## 13.1 Knowledge Graph
286 -
287 -A pre-built dependency graph is available at `.aiassistant/graph/dependency-graph.json`.
288 -
289 -Before exploring the codebase structure (finding a class, tracing dependencies, exploring namespaces), **read this file first**. It contains:
290 -- `nodes`: per-file namespace, declared symbols, and imports.
291 -- `symbol_index`: maps every fully-qualified PHP class/interface/trait/enum to its file.
292 -
293 -Run `node bin/build-knowledge-graph.js` to refresh after structural changes (`--full` to force rebuild).
294 -
295 -
296 -# 15. Repository Specs
297 -
298 -The repository may define task-specific implementation specs under `.aiassistant/specs/`.
299 -
300 -Specs provide detailed guidance for recurring technical problems
301 -(e.g. PHPCS warnings, architecture migrations, WordPress compliance patterns).
302 -
303 -When a relevant spec exists, agents must follow it in addition to AGENTS.md and the applicable skills.
304 -
305 -
306 -# AI Task Priority
307 -
308 -When executing tasks, agents must prioritize:
309 -
310 154 1. Security
311 155 2. WordPress.org compliance
312 156 3. Architectural integrity
313 157 4. Backward compatibility
@@ -320,6 +156,4 @@
320 156 3. Architectural integrity
321 157 4. Backward compatibility
322 158 5. Minimal diffs
323 159 6. Performance
324 -
325 -AGENTS.md remains the final authority.