| 1 |
# Transplant Context: Imagify |
| 2 |
|
| 3 |
**Target:** `/Users/gaelrobin/Local Sites/imagify/app/public/wp-content/plugins/imagify-plugin` |
| 4 |
**Analysed:** 2026-06-10 |
| 5 |
**Analyst model:** Claude Opus 4.8 |
| 6 |
|
| 7 |
> Primary source of truth for customizations: `.aiassistant/transplant-preservation.md`. |
| 8 |
> The project already contains an adapted workflow under `.aiassistant/` (skills, agents, specs, |
| 9 |
> repo-map, issue-sync script, PR template). The writers must carry forward every item documented |
| 10 |
> in the preservation file into the new `.claude/` output. |
| 11 |
|
| 12 |
--- |
| 13 |
|
| 14 |
## 1. Project Identity |
| 15 |
|
| 16 |
| Field | Value | |
| 17 |
|---|---| |
| 18 |
| Name | Imagify | |
| 19 |
| Type | wp-plugin | |
| 20 |
| Primary language | PHP (with TypeScript for E2E + JS/SCSS frontend source) | |
| 21 |
| Framework | WordPress | |
| 22 |
| Runtime / version | PHP >= 7.3 (CI matrix 8.0–8.4); WordPress (wp-env core: latest, phpVersion 8.2) | |
| 23 |
|
| 24 |
--- |
| 25 |
|
| 26 |
## 2. Stack |
| 27 |
|
| 28 |
### Backend |
| 29 |
|
| 30 |
| Field | Value | |
| 31 |
|---|---| |
| 32 |
| Language | PHP | |
| 33 |
| Framework | WordPress plugin | |
| 34 |
| Test runner | PHPUnit (^8.5.52 \|\| ^9.6.33) | |
| 35 |
| Test command | `composer run-tests` (= `composer test-unit` + `composer test-integration`) | |
| 36 |
| Static analysis | PHPCS (WPCS ^3) + PHPStan (level 5, szepeviktor/phpstan-wordpress) | |
| 37 |
| Lint command | `composer phpcs` (full) / `composer phpcs-changed` (./bin/phpcs-changed.sh) / `composer run-stan` | |
| 38 |
| Package manager | composer (PHP) + npm (frontend/E2E) | |
| 39 |
| Key config files | composer.json, phpcs.xml, phpstan.neon.dist, .wp-env.json, config/providers.php | |
| 40 |
|
| 41 |
Notes: |
| 42 |
- Unit suite config: `Tests/Unit/phpunit.xml.dist`; integration: `Tests/Integration/phpunit.xml.dist`. |
| 43 |
- Strauss prefixes vendored deps into `Imagify\Dependencies\` (classmap prefix `Imagify_`). `composer install` runs `prefix-namespaces` automatically (post-install/post-update). |
| 44 |
- DI: `league/container` (Strauss-prefixed to `Imagify\Dependencies\League\Container\Container`). ServiceProviders per module under `classes/*/ServiceProvider.php`, registered in `config/providers.php`. Hooks via `SubscriberInterface` listed in `ServiceProvider::get_subscribers()`. |
| 45 |
- Dual-layer architecture (see Analyst Notes): modern `classes/` (PSR-4, `Imagify\`, `declare(strict_types=1)`) vs legacy `inc/classes/` (`Imagify_` prefix, do not extend). |
| 46 |
|
| 47 |
### Frontend |
| 48 |
|
| 49 |
| Field | Value | |
| 50 |
|---|---| |
| 51 |
| Present | yes | |
| 52 |
| Framework | Vanilla JS + SCSS (jQuery-era admin scripts) | |
| 53 |
| Build tool | Grunt (root `gruntfile.js`, `npm run build`); `_dev/` also has a `bud.config.js` (Bud/webpack) + own package.json | |
| 54 |
| Asset source paths | `_dev/` (src), `_dev/src/` | |
| 55 |
| Compiled asset paths | `assets/` (do not edit directly) | |
| 56 |
| Test runner | N/A for frontend unit (no Jest/Vitest); behaviour covered by Playwright E2E | |
| 57 |
|
| 58 |
--- |
| 59 |
|
| 60 |
## 3. Dev Environment |
| 61 |
|
| 62 |
| Field | Value | |
| 63 |
|---|---| |
| 64 |
| Boot mechanism | wp-env (via project wrapper scripts in `bin/`) | |
| 65 |
| Start command | `bash bin/dev-up.sh` (flags: `--no-seed`, `--reset`) | |
| 66 |
| Stop command | `bash bin/dev-down.sh` (flag: `--clean` for full destroy) | |
| 67 |
| Seeding | yes | |
| 68 |
| Seed command | `bash bin/dev-seed.sh` (sets Imagify API key from IMAGIFY_TESTS_API_KEY, uploads a test JPEG) | |
| 69 |
| Local URL | http://localhost:8888 | |
| 70 |
| Admin / dashboard URL | http://localhost:8888/wp-admin (admin / password) | |
| 71 |
| Temp root | .ai | |
| 72 |
| Notes | wp-env tests instance on :8889 (used by PHPUnit). dev-up runs `composer install` + `@wordpress/env start` + activates `imagify` + seeds. .env.local (gitignored) supplies IMAGIFY_TESTS_API_KEY, auto-sourced by bin/test-e2e.sh. DISCREPANCY: interview temp_root=.ai is authoritative, but existing issue-sync.sh + .gitignore use `.TemporaryItems/Issues/imagify-plugin/...`. See Analyst Notes. | |
| 73 |
|
| 74 |
--- |
| 75 |
|
| 76 |
## 4. Browser / E2E Testing |
| 77 |
|
| 78 |
| Field | Value | |
| 79 |
|---|---| |
| 80 |
| Framework | Playwright (TypeScript) | |
| 81 |
| Config path | Tests/e2e/playwright.config.ts | |
| 82 |
| Base URL | http://localhost:8888 (env override: IMAGIFY_BASE_URL) | |
| 83 |
| Test directory | Tests/e2e/specs/ (fixtures: Tests/e2e/fixtures/, page objects: Tests/e2e/pages/) | |
| 84 |
| CI integration | yes (.github/workflows/e2e.yml) | |
| 85 |
|
| 86 |
Run command: `bash bin/test-e2e.sh` (flags: `--headed`, `--ui`, or a spec pattern). Chromium-only, single worker, `fullyParallel:false`. Screenshots go to `.e2e-screenshots/` (gitignored). Page objects: SettingsPage, BulkOptimizationPage, MediaLibraryPage. API-key-gated tests use `test.skip(!process.env.IMAGIFY_TESTS_API_KEY, ...)`. |
| 87 |
|
| 88 |
--- |
| 89 |
|
| 90 |
## 5. CI/CD |
| 91 |
|
| 92 |
| Field | Value | |
| 93 |
|---|---| |
| 94 |
| Platform | GitHub Actions | |
| 95 |
| Workflow files | .github/workflows/test.yml, test_legacy.yml, e2e.yml, lint_phpcs.yml, lint_phpstan.yml, code_coverage.yml, pr-template-checker.yml, assets-update.yml, deploy-tag.yml | |
| 96 |
| Test job name | "Unit/Integration tests" (job `run`); steps: `composer test-unit`, `composer test-integration` | |
| 97 |
| Lint job name | "PHPCS" (job `run`, `composer phpcs`); separate "PHPStan" workflow (lint_phpstan.yml) | |
| 98 |
| Build job name | assets-update.yml / deploy-tag.yml (no dedicated PR build job) | |
| 99 |
|
| 100 |
Notes: PR-template-checker uses `wp-media/pr-checklist-action`. test.yml installs Strauss before composer install and runs install-wp-tests.sh against MySQL. PR target branches: trunk, develop, branch-*, feature/*, enhancement/*, fix/*. |
| 101 |
|
| 102 |
--- |
| 103 |
|
| 104 |
## 6. GitHub |
| 105 |
|
| 106 |
| Field | Value | |
| 107 |
|---|---| |
| 108 |
| Repo | wp-media/imagify-plugin | |
| 109 |
| Base branch | develop | |
| 110 |
| PR template | `.aiassistant/skills/issue-workflow/refs/pr-template.md` (no `.github/PULL_REQUEST_TEMPLATE.md`; checker action enforces format) | |
| 111 |
|
| 112 |
--- |
| 113 |
|
| 114 |
## 7. Source Structure |
| 115 |
|
| 116 |
``` |
| 117 |
imagify.php / uninstall.php # bootstrap + uninstall entrypoints |
| 118 |
classes/ # modern PSR-4 (Imagify\), strict_types=1 — new code here |
| 119 |
inc/ |
| 120 |
classes/ # legacy Imagify_ classmap (do not extend) |
| 121 |
3rd-party/ # PSR-4 integrations (WC, AS3CF, NGG, WP Rocket, ...) |
| 122 |
Dependencies/ActionScheduler/ # vendored (do not edit) |
| 123 |
functions/ # legacy global helpers |
| 124 |
admin/ common/ deprecated/ # legacy admin / shared / deprecated |
| 125 |
views/ # PHP admin templates |
| 126 |
_dev/ # frontend source (JS/SCSS, Grunt + bud.config.js) -> assets/ |
| 127 |
assets/ # compiled frontend (do not edit) |
| 128 |
config/providers.php # service provider registry |
| 129 |
bin/ # dev-up.sh, dev-down.sh, dev-seed.sh, test-e2e.sh, build-knowledge-graph.js, install-wp-tests.sh |
| 130 |
Tests/ |
| 131 |
Unit/ Integration/ Fixtures/ phpstan/ # PHPUnit |
| 132 |
e2e/ # Playwright (specs/ fixtures/ pages/) |
| 133 |
config/ vendor/ node_modules/ |
| 134 |
``` |
| 135 |
|
| 136 |
### Areas (for maestro.json) |
| 137 |
|
| 138 |
| Path | Role | Notes | |
| 139 |
|---|---|---| |
| 140 |
| classes/ | source | Modern PSR-4 `Imagify\`, strict_types=1. New features go here. | |
| 141 |
| inc/classes/ | source | Legacy `Imagify_` classmap. Do not add new classes; migrate out. | |
| 142 |
| inc/3rd-party/ | source | PSR-4 third-party integrations (WC, AS3CF, NGG, WP Rocket). | |
| 143 |
| inc/Dependencies/ | vendor | Vendored ActionScheduler. Do not edit. | |
| 144 |
| inc/functions/ | source | Legacy global helpers; migrating to services. | |
| 145 |
| inc/admin/ | source | Legacy admin includes. | |
| 146 |
| inc/common/ | source | Shared legacy includes. | |
| 147 |
| inc/deprecated/ | source | Deprecated classes/traits. Do not add or delete. | |
| 148 |
| views/ | source-frontend | PHP admin templates. | |
| 149 |
| _dev/ | source-frontend | Frontend source (JS/SCSS). Compiled to assets/. | |
| 150 |
| assets/ | assets | Compiled frontend assets. Do not edit directly. | |
| 151 |
| config/ | config | Plugin config; providers.php = service provider registry. | |
| 152 |
| bin/ | tooling | Dev and CI scripts. | |
| 153 |
| Tests/ | tests | PHPUnit unit + integration (capital T). | |
| 154 |
| Tests/e2e/ | tests | Playwright E2E (TypeScript). | |
| 155 |
| vendor/ | vendor | Composer deps. Do not edit. | |
| 156 |
| node_modules/ | vendor | NPM deps. Do not edit. | |
| 157 |
|
| 158 |
--- |
| 159 |
|
| 160 |
## 8. Workflow Component Disposition |
| 161 |
|
| 162 |
| Component | Decision | Reasoning | |
| 163 |
|---|---|---| |
| 164 |
| `agents/grooming-agent.md` | ADAPT | WP-plugin grooming; reference dual-layer architecture + repo-map. | |
| 165 |
| `agents/challenger.md` | KEEP_AS_IS | Project-agnostic. | |
| 166 |
| `agents/backend-agent.md` | ADAPT | PHP/WordPress backend. Wire to PHPUnit (`composer run-tests`), PHPCS/PHPStan, classes/ vs inc/classes/ rules, DI container + ServiceProvider/Subscriber patterns, anti-patterns (no get_instance/InstanceGetterTrait in classes/), PHPCS specs. | |
| 167 |
| `agents/frontend-agent.md` | ADAPT | Frontend exists (_dev/ JS/SCSS -> assets/, Grunt + bud). No JS unit runner; verification via build + Playwright. Do-not-edit assets/. | |
| 168 |
| `agents/lead-reviewer.md` | ADAPT | Reference repo conventions (minimal diffs, dual-layer, escaping/nonce/sanitize specs). | |
| 169 |
| `agents/qa-engineer.md` | ADAPT | DOD Check 2 -> PHPUnit (`composer test-unit`/`test-integration`); align with preserved .aiassistant/agents/qa-engineer.md. | |
| 170 |
| `agents/e2e-qa-tester.md` | ADAPT | Browser-testable UI present. Carry forward Imagify env: localhost:8888, admin/password, bin/dev-up.sh + dev-seed.sh, admin routes, selectors, POM files, API-key guard, SHA-based screenshot publishing (preservation file §4 + .aiassistant/agents/e2e-qa-tester.md). | |
| 171 |
| `agents/release-agent.md` | KEEP_AS_IS | Generic git/gh. | |
| 172 |
| `agents/ticket-writer.md` | ADAPT | Repo reference -> wp-media/imagify-plugin. | |
| 173 |
| `commands/orchestrator.md` | ADAPT | Constants: REPO=wp-media/imagify-plugin, base develop, temp_root, script paths. | |
| 174 |
| `commands/issue-workflow.md` | ADAPT | Script paths, config keys, temp_root, base branch origin/develop (explicit). | |
| 175 |
| `commands/dod.md` | ADAPT | Check 2 = PHPUnit; add PHPCS/PHPStan gates; E2E via Playwright. | |
| 176 |
| `commands/e2e.md` | ADAPT | Playwright present; wire to bin/test-e2e.sh + Tests/e2e config. | |
| 177 |
| `commands/docs.md` | KEEP_AS_IS | Generic. | |
| 178 |
| `commands/compliance.md` | KEEP_AS_IS | WP project — keep (PHP escaping/nonce/sanitize). Align with .aiassistant/skills/wordpress-compliance/SKILL.md + specs/phpcs/. | |
| 179 |
| `commands/knowledge-graph.md` | ADAPT | Project has bin/build-knowledge-graph.js + .aiassistant/skills/knowledge-graph/SKILL.md; wire paths. | |
| 180 |
| `scripts/issue-sync.sh` | ADAPT | NOT pure-generic here: must hardcode REPO=wp-media/imagify-plugin and the issue/PR output paths, plus the GraphQL epic/sub-issue detection logic (preservation §5). Existing version: .aiassistant/skills/issue-workflow/scripts/issue-sync.sh (uses .TemporaryItems — reconcile with temp_root .ai). | |
| 181 |
| `scripts/make-issue-branch.sh` | ADAPT | Base branch must be explicit origin/develop (preservation §5); otherwise generic. Existing: .aiassistant/skills/issue-workflow/scripts/make-issue-branch.sh. | |
| 182 |
| `scripts/init-pr-draft.sh` | KEEP_AS_IS | Generic (existing: .aiassistant/skills/issue-workflow/scripts/init-pr-draft.sh). | |
| 183 |
| `refs/pr-template.md` | ADAPT | Imagify-specific sections (Affected Features & QA Scope; Technical description: Documentation/Dependencies/Risks; Mandatory Checklist: Code validation + Code style; Unticked justification; Additional Checks). Preserve AI guardrail comment. Source: .aiassistant/skills/issue-workflow/refs/pr-template.md (preservation §6). | |
| 184 |
| `bin/dev-start.sh` | ADAPT | wp-env based. Mirror existing bin/dev-up.sh (--no-seed/--reset, preflight, composer install, wp-env start, activate imagify, seed). | |
| 185 |
| `bin/dev-seed.sh` | REWRITE | Seeding exists and is Imagify-specific (API key from IMAGIFY_TESTS_API_KEY, test JPEG upload). Mirror existing bin/dev-seed.sh. | |
| 186 |
| `bin/dev-down.sh` | ADAPT | wp-env stop/destroy. Mirror existing bin/dev-down.sh (--clean). | |
| 187 |
|
| 188 |
Counts: KEEP_AS_IS = 4 (challenger, release-agent, docs, init-pr-draft) + compliance KEEP = 5; ADAPT = 17; REWRITE = 1 (dev-seed); DROP = 0. |
| 189 |
|
| 190 |
--- |
| 191 |
|
| 192 |
## 9. Analyst Notes |
| 193 |
|
| 194 |
- **Existing adapted workflow already present.** `.aiassistant/` contains a previously-tailored Imagify workflow (skills imagify-architecture / issue-workflow / knowledge-graph / wordpress-compliance, agents qa-engineer + e2e-qa-tester, specs/phpcs/*, config/repo-map.json, scripts, pr-template). Writers should treat these as the de-facto baseline and port their content into the new `.claude/` layout rather than regenerating blind. `.aiassistant/transplant-preservation.md` is the authoritative checklist. |
| 195 |
- **Dual-layer PHP architecture (hard constraint).** New code -> `classes/` (PSR-4 `Imagify\`, `declare(strict_types=1)`). Never add classes to `inc/classes/` (legacy `Imagify_`); migrate out instead. Anti-patterns to reject: `get_instance()`, `InstanceGetterTrait`, global state/static helpers replacing services. DI = Strauss-prefixed league/container; providers registered in `config/providers.php`; hooks via `SubscriberInterface` in `ServiceProvider::get_subscribers()`. |
| 196 |
- **temp_root discrepancy (resolve in writer step).** Interview is authoritative: `temp_root = .ai`. But the live `issue-sync.sh` and `.gitignore` use `.TemporaryItems/Issues/imagify-plugin/...`. The generated workflow should standardize on `.ai`; the writer should also add `/.ai` to `.gitignore` (currently only `/.TemporaryItems` is ignored) or keep `.TemporaryItems` if the team prefers continuity — flag for human confirmation. |
| 197 |
- **Three PHPCS sniffs are excluded in phpcs.xml** (NonceVerification.Missing, NonceVerification.Recommended, plus output/sanitize handled "later"). The compliance command + specs/phpcs/ guides (escaped-output, nonce-verification-recommended, validated-sanitized-input) document the correct remediation patterns; nonce action naming convention is `imagify_<feature>_<action>`. Do not blanket-add `phpcs:ignore`. |
| 198 |
- **Strauss build step is mandatory** before tests/lint: `composer install` auto-runs `prefix-namespaces`. Any CI/agent that runs PHPUnit/PHPCS must ensure Strauss + composer install ran first (CI does this explicitly). |
| 199 |
- **Single-edition plugin** — no FREE/PRO split. Remove the editions block from maestro.json. |
| 200 |
- **E2E env specifics** must survive: localhost:8888, admin/password, bin/dev-up.sh (idempotent) + bin/dev-seed.sh, screenshots in `.e2e-screenshots/`, API-key guard `test.skip(!process.env.IMAGIFY_TESTS_API_KEY,...)`, and SHA-based raw.githubusercontent.com screenshot URLs for QA reports. |
| 201 |
- **No frontend JS unit runner** (no Jest/Vitest); frontend verification = `npm run build` (Grunt) + Playwright. Do not invent a JS unit gate. |
| 202 |
- `.aiassistant` is `export-ignore` in `.gitattributes` (excluded from dist) — safe location; the new `.claude/` output is the runtime home. |
| 203 |
|