php-modernization — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited php-modernization (Plugin) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Expert patterns for modernizing PHP applications to PHP 8.x with type safety, PSR / PER-CS compliance, static-analysis tooling, and Symfony-grade architecture. The skill ships an agent contract — a small set of executable tools that emit machine-readable verification reports, archetype profiles, and fix-loop transcripts.
This is an Agent Skill following the open standard originally developed by Anthropic and released for cross-platform use.
Supported platforms:
Skills are portable packages of procedural knowledge that work across any AI agent supporting the Agent Skills specification.
verify_php_project.py), orchestrator (modernize_loop.py), and cheap profiler (introspect.py). stable structured output (JSON with schema_version 1.0.0, SARIF 2.1.0, or JUnit XML), archetype detection, and machine-readable agent_actions[] recommendations downstream agents can act on without re-reading the prose references.SKILL.md (no readonly on Doctrine entities, no Rector without --dry-run, baseline shrink-not-delete, no blanket final on mock targets, no editing generated files).array_find / array_any / array_all), and dedicated 8.5 reference (released 2025-11: pipe |>, array_first / array_last, #[\NoDiscard]).@PER-CS), Infection (mutation testing in PR-diff mode), composer audit.readonly vs. property hooks vs. classic mutation).generic-composer, typo3-extension, symfony-app, monorepo-package. The verifier and orchestrator branch on archetype.The skill follows a four-step loop. Cheap commands first; expensive analysis only when needed.
SKILL.md, then profile the project.--mode dry-run before mutating files.references/<topic>.md only when the long-form rationale is needed.# Cheap first-touch profile (no subprocesses except `php --version`)
uv run skills/php-modernization/scripts/introspect.py --root .
# Full mechanical verification with agent_actions[]
uv run skills/php-modernization/scripts/verify_php_project.py --root . --format json --summary
# One checkpoint at a time
uv run skills/php-modernization/scripts/verify_php_project.py --root . --check PM-02
# Orchestrated fix preview (no mutations; use --confirm to apply)
uv run skills/php-modernization/scripts/modernize_loop.py --mode dry-runuv is the recommended runner for the Python tools (it resolves the PEP 723 inline dependencies automatically). The Bash wrapper transparently falls back to python3 if uv is not installed.
verify_php_project.py accepts --format json | sarif | junit. JSON is the canonical contract (see schemas/verification-result.schema.json). SARIF 2.1.0 plugs into the GitHub Security → Code scanning tab. JUnit XML is convenient for CI dashboards. Checkpoint IDs (PM-XX) are stable forever — never renumbered.
The five guardrails below are binding. The agent must refuse rather than violate them.
readonly to Doctrine entities or mapped-superclasses (embeddables are a nuanced case, ORM 3.x dependent — see references/doctrine-modernization-edges.md).--dry-run first.final to mock targets or extension points without confirmation.@generated files or files under var/cache/, vendor/, node_modules/, .Build/.The full table of references is in SKILL.md.
Add the Netresearch marketplace once, then browse and install skills.
# Claude Code
/plugin marketplace add netresearch/claude-code-marketplaceInstall with any Agent Skills-compatible agent:
npx skills add https://github.com/netresearch/php-modernization-skill --skill php-modernizationcomposer require netresearch/php-modernization-skillRequires netresearch/composer-agent-skill-plugin.
Download the latest release and extract to your agent's skills directory.
git clone https://github.com/netresearch/php-modernization-skill.gitThe skill auto-triggers on PHP modernization work: type-safety enforcement, PHPStan / Rector / PHP-CS-Fixer / PHPat setup, PSR / PER-CS compliance, Symfony patterns, version upgrades from 7.x or 8.0–8.3 baselines, and PHP 8.4 / 8.5 feature adoption.
Example queries:
readonly usage."templates/composer-scripts.json is a drop-in scripts block for composer.json. Highlights:
cs:fix, cs:check — PHP-CS-Fixer apply / dry-runphpstan — analysis without progress bar (CI-friendly)rector, rector:check — apply / dry-runphpat, audit — architecture tests + composer advisoriesskill:inspect, skill:verify — introspector / verifier shortcutsskill:fix, skill:qa — convenience pipelinesThe script-name conventions (cs:fix, phpstan, rector) map onto checkpoints PM-13, PM-14, PM-15 — adopting them lights those checks green automatically. See templates/README.md for full guidance.
templates/github-actions/php-modernization.yml is a copy-and-modify GitHub Actions workflow. It runs the verifier, optionally uploads SARIF to the Security → Code scanning tab, runs the orchestrator in --mode dry-run (with Infection diff-mode against the PR base), uploads artifacts, and posts a PR summary comment on failure. Adjust the php-version matrix to match your project's PHP requirement.
The verifier and orchestrator branch on archetype. Detection is pure (no subprocesses) and lives in scripts/_common.py::detect_archetype. Priority order:
| Archetype | Detection signal |
|---|---|
typo3-extension | ext_emconf.php or Configuration/Services.yaml |
symfony-app | bin/console plus config/bundles.php |
monorepo-package | packages/<name>/composer.json for two or more children |
generic-composer | composer.json plus src/ plus tests/ |
A regression suite under fixtures/ covers each archetype plus a fully-modern/ positive control where every check passes. See fixtures/README.md for the snapshot workflow.
php-modernization-skill/
├── skills/php-modernization/
│ ├── SKILL.md # Agent contract (router + guardrails)
│ ├── checkpoints.yaml # PM-XX checkpoints
│ ├── references/ # 19 lazy-loaded reference docs
│ ├── scripts/ # verify_php_project.py + orchestrator + introspector
│ └── templates/ # composer-scripts.json + GitHub Actions workflow
├── schemas/ # JSON Schema 2020-12 (output contracts)
├── fixtures/ # Synthetic-project regression suite
├── scripts/ # test_fixtures.py + verify-harness.sh
├── docs/ARCHITECTURE.md # Architecture overview
├── evals/ # Skill evaluation suite
├── composer.json # Composer manifest
├── .claude-plugin/plugin.json # Claude Code plugin manifest
└── sonar-project.properties # SonarCloud config (excludes fixtures)| Tool | Purpose | Requirement |
|---|---|---|
| PHPStan | Type checking, bug detection | Level 9 minimum, level 10 recommended |
| PHPat | Architecture testing | Required for projects with defined layer boundaries |
| Rector | Automated refactoring | Required for modernization (always dry-run first) |
| PHP-CS-Fixer | Coding style | Required with @PER-CS |
| Infection | Mutation testing | Required in PR-diff mode |
| Standard | Purpose | Notes |
|---|---|---|
| PSR-1 | Basic Coding | Required |
| PSR-4 | Autoloading | Required |
| PER Coding Style | Coding style | Required (supersedes PSR-12) |
| PSR-12 | Extended coding style | Superseded by PER-CS — do not use |
| PSR-3 | Logger | When logging |
| PSR-6 / PSR-16 | Cache | When caching |
| PSR-7 / PSR-17 / PSR-18 | HTTP messages, factories, client | For HTTP clients |
| PSR-11 | Container | For DI containers |
| PSR-13 | Hypermedia links | For HATEOAS responses |
| PSR-14 | Events | For event dispatching |
| PSR-15 | HTTP middleware | See references/psr15-middleware-architecture.md |
| PSR-20 | Clock | For time-dependent code |
Source of truth: php-fig.org/psr and php-fig.org/per.
Never pass or return raw arrays for structured data. Use typed objects.
| Instead of | Use |
|---|---|
array $userData | UserDTO $user |
array{email: string, name: string} | readonly class UserDTO |
array $config | readonly class Config or Value Object |
array $request | RequestDTO::fromRequest($request) |
return ['success' => true, 'data' => $x] | return new ResultDTO($x) |
Why: arrays lack runtime type safety, IDE autocompletion, and refactor-friendliness; PHPStan cannot verify array shapes across boundaries. Full patterns including Request DTOs, Command/Query DTOs, and Value Objects live in references/request-dtos.md. Immutability rules — when readonly applies, when property hooks fit better, when classic mutation is correct — are in references/immutability-boundaries.md.
Never use string or integer constants, or arrays of literals, for fixed value sets. Use PHP 8.1+ backed enums.
| Instead of | Use |
|---|---|
const STATUS_DRAFT = 'draft' | enum Status: string { case Draft = 'draft'; } |
['draft', 'published', 'archived'] | Status::cases() |
string $status parameter | Status $status parameter |
switch ($status) | match ($status) with enum |
Why: compile-time type checks, IDE autocompletion, exhaustive match() enforcement, and methods that encapsulate label / colour / validation logic. Full patterns are in references/php8-features.md.
declare(strict_types=1) everywhere@PER-CS ruleset, no deprecated PHP-CS-Fixer aliasestreatPhpDocTypesAsCertain: false (level 10 for new projects)#[Override] (8.3+), #[SensitiveParameter] (8.2+), typed constants (8.3+)readonly on DTOs / VOs / events only — see immutability boundariesarray_find / array_any / array_all over manual loops (8.4)|> for transform pipelines (8.5)PM-26/27/28/33/35/36 were relocated there).This project uses split licensing:
See the individual license files for full terms.
Developed and maintained by Netresearch DTT GmbH.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.