Contributing
August 18, 2026 · View on GitHub
Thanks for wanting to help. This is the short human version — AGENTS.md is the full
contract for both humans and automated tools, and it defers to
z-engine's AGENTS.md for everything
about the engine itself.
Before you start
- Run only supported PHP minors. Engine struct layouts are version-specific; z-engine tracks
one minor per release line, and the
~8.4.2 || ~8.5.0constraint makes composer resolve the stable line matching your PHP, so this package supports both minors in parallel. Anything newer (8.6 nightly) installs but cannot touch the engine yet. - Develop against a debug build (
--enable-debug, FFI on). It turns silent memory corruption into loud assertion failures. - FFI must be enabled (
ffi.enable=1) and the JIT disabled (opcache.jit=off).
Setup
composer install
php -d ffi.enable=1 -d opcache.jit=off vendor/bin/phpunit # or: composer test
composer phpstan
composer cs:check
composer test:internal # destructive class-table eviction; a debug build also reports leaks
composer test:preload # boots preload.php in a child process, needs opcache
composer test:analysis runs only the static-analysis tests and needs neither FFI nor a matching
PHP build, so you can work on the PHPStan extension anywhere.
Making changes
- Keep the code clean at PHPStan level max and at
cs:check. - Never read a doc comment in the runtime path — attributes are the runtime source of truth
(see
AGENTS.md§2). Thetests-opcacheCI job enforces this. - Validate everything before calling into the engine, so a rejection can never leave a half-registered class behind.
- Add a static named constructor for every new failure mode instead of an inline
throw. - Give every test that registers a specialization a unique target name.
- Add or update tests, and update
docs/when behaviour changes —design.mdfor how the engine is driven,static-analysis.mdfor the extension. - If you touch a template fixture or the stub generator, run
composer stubs:generate. The stubs undertests/phpstan/generated/are committed andcomposer stubs:checkruns in CI, so hand-editing one works only until the next run throws the edit away. - Never hand-edit
docs/benchmarks.md— it is written bycomposer bench, and every sentence under a table is computed from that run. If a number needs explaining, explain it in the scenario that produces it. - Use Conventional Commits.
Pull request checklist
-
composer testpasses on every supported PHP minor (CI runs 8.4 and 8.5) -
composer phpstanandcomposer cs:checkare green -
composer stubs:checkis green if you touched a template or the generator - tests added or updated, with unique specialized class names
- docs updated if behaviour changed
- conventional commit messages
Reporting bugs
Include the first line of php -v, whether the build is NTS or ZTS, your OS and architecture, the
installed z-engine version, and a minimal template class that reproduces the problem.