Project Configuration values below override a pipeline's derived defaults. Behaviour — how agents run, dispatch, or report — belongs to the pipeline, not to this file.
| Variable | Value |
|---|---|
REPO |
wp-media/imagify-plugin |
SLUG / TEXT_DOMAIN |
imagify |
BASE_BRANCH |
develop |
| Protected branches | develop, master — never commit directly |
| Branch naming | <prefix>/<issue>-<slug>; prefix fix (bugs), enhancement (features, incl. feat commits), test |
| Test (full / unit / integration) | composer run-tests / composer test-unit / composer test-integration |
| Test (one group) | vendor/bin/phpunit --configuration Tests/Integration/phpunit.xml.dist --group <Name> |
| Lint / auto-fix | composer phpcs / composer phpcbf |
| Static analysis | composer run-stan |
| Build frontend | npm run build |
| Local env up / down / seed | bash bin/dev-up.sh / bash bin/dev-down.sh / bash bin/dev-seed.sh |
| E2E runner | bash bin/test-e2e.sh (--headed, --ui, or a spec path) |
| Local URL | http://localhost:8888 — admin admin / password |
| Settings page | /wp-admin/options-general.php?page=imagify |
| Key option | imagify_settings (API key + config) |
| PR template | .github/PULL_REQUEST_TEMPLATE.md |
.env.local at the repo root (gitignored) holds IMAGIFY_TESTS_API_KEY=<key>. The same value must
exist as a GitHub secret for CI optimization tests.
Things that fail in ways you will not notice.
- Run
composer installbefore any test or lint command. Strauss namespace-prefixing is a Composer post-install hook. Without it, PHPCS and PHPUnit cannot resolveImagify\Dependencies\*and fail with misleading autoload errors. WordPress.Security.NonceVerification.Missingand.Recommendedare deliberately suppressed inphpcs.xml. Do not addphpcs:ignorefor them and do not restructure code to satisfy them.assets/is build output. Edit_dev/and rebuild, or the next build discards your work.- There is no JavaScript unit test runner (no Jest, no Vitest). Never invent
npm test. Frontend verification isnpm run buildplus Playwright; otherwise report JS tests asN/A. - Optimization behaviour sits behind license, API-key and quota guards. Before reporting that a
feature works or is broken, run
bash bin/dev-seed.shand confirm the key landed:npx @wordpress/env run cli wp option get imagify_settings --format=json | grep -c '"api_key":"[^"]\+'Only once the key is present (result1) may you treat a guard as a genuine blocker. Never report a behavioural pass or failure through a blocked guard — report "cannot verify" with the guard'sfile:line. Guard locations are in thee2eskill. - A PR's number is not its issue number. Read it back from the
gh pr createoutput. - PHP-rendered admin UI is a frontend change.
wp_admin_notice(),add_action( 'admin_notices', ... )andadd_settings_error()need frontend scoping and testing despite living in PHP.
Single-edition plugin — no FREE/PRO split. Namespace root Imagify\, PSR-4 root classes/.
classes/— modern PSR-4,declare(strict_types=1)required. New features go here.inc/classes/— legacy classmap,Imagify_prefix, migrating towardclasses/. Add nothing here.
In new classes/ code:
- No new singletons or
InstanceGetterTraitusage. The trait is still used inclasses/Plugin.php,classes/Bulk/Bulk.phpand elsewhere — that is legacy precedent, not a pattern to copy. - No bare
add_action()/add_filter(). Register hooks through aSubscriberimplementingSubscriberInterface, listed inServiceProvider::get_subscribers(). - Service providers live at
classes/*/ServiceProvider.phpand are registered inconfig/providers.php. - No global state, and no UI logic coupled to infrastructure logic. The legacy
inc/layer is procedural and full of both — do not pattern-match from it.
Nonce action naming: imagify_<feature>_<action>.
DI container is Strauss-prefixed: Imagify\Dependencies\League\Container\Container — a plain
use League\Container\Container; is wrong here. Async work uses ActionScheduler, not wp-cron.
Frontend source is _dev/ (Grunt, gruntfile.js); _dev/ also carries its own bud.config.js.
Source of truth: composer.json scripts, phpcs.xml, phpstan.neon.dist, CI. Never hardcode PHPCS
standards or invent lint commands.
Imagify must stay WordPress.org-compatible (Plugin Check). Evaluate any change to public APIs, output, security, metadata, or bootstrap behaviour against it.
- PHP 7.4+, strict types in all new
classes/files. - Text domain
imagify:esc_html__( 'Label', 'imagify' ). - Authorization: use the project's registered capability (
'bulk-optimize','manage', …) incurrent_user_can(), never the coarsemanage_options. - No jQuery in new or modified JavaScript — native DOM APIs only, no inline handlers, no unsafe
innerHTML. Pass nonces viawp_localize_script. - Remote responses from the Imagify API are untrusted input and are this plugin's main attack surface. Validate and escape everything that comes back before storing or echoing it.
Prefer integration tests (Tests/Integration/, annotated @group FeatureName) — they exercise
real WordPress context, DI wiring and hook execution. Unit tests only for pure logic with no WP
globals, container or hooks.
Scale scope to risk: LOW = the relevant --group; MEDIUM = composer test-unit plus that group;
HIGH = composer run-tests.
Not scope violations: generated files (*.min.js, *.min.css), lockfiles, tests mirroring changed
source, auto-formatter output.
- Conventional Commits:
type(scope): short description. Each commit passes PHPCS and static analysis before being made. - Pipeline-authored commits carry a
Co-Authored-By: <model> <noreply@anthropic.com>trailer so automated work stays auditable. Human-authored commits do not. - Do not squash unrelated changes. Do not amend commits already pushed.
- Outside a pipeline working a specific ticket, only suggest commits — do not run
git commitorgit push. - PR title:
Closes #<N>: <short title>— never a Conventional-Commit prefix; that is for commits. - The PR body needs a standalone
Closes #<N>line, not buried in prose — that is what auto-closes. - Apply the
Made by AIlabel to every AI-created PR and issue. - Split work vertically: each PR one complete behaviour including its tests. Never a backend PR plus a separate frontend PR for one feature, even when separate agents did the work.
- Do not run large automated refactors or reorganize files without being asked. The legacy-to-modern migration is ongoing; "cleaning up while I'm here" is not in scope.
- Browser testing — admin URLs, page objects, environment variables, local running:
docs/E2E_TESTING.md - QA procedure — tiers, spec conventions, guard locations: the
e2eskill (.claude/skills/e2e/) - Code structure — use the installed pipeline's knowledge-graph skill if it provides one. A local
builder also exists:
node bin/build-knowledge-graph.jswrites.aiassistant/graph/(gitignored). Do not mix the two graphs in one session; if neither is current, use grep rather than stopping.
When these conflict, earlier wins:
- Security
- WordPress.org compliance
- Architectural integrity
- Backward compatibility
- Minimal diffs
- Performance