# Rector (automated refactoring) Modernisation tool for the Crewli backend. Provides automated refactoring against PHP-version and Laravel-version rule sets. ## Running locally - `composer rector` — DRY-RUN. Lists proposed changes, modifies nothing. Default mode for safety. Exit code is 2 when suggestions exist, 0 when the codebase is clean — this is Rector's convention and NOT an error state. - `composer rector:apply` — APPLIES changes. Use only inside a scoped reduction sprint with a planned set of rule-applications. - `composer rector:clear-cache` — clear Rector cache. Memory: 2G default. Bump to 4G if OOM. ## The dry-run-then-apply model Rector configuration in `rector.php` defines the rule sets that SHOULD apply. `composer rector` reports what WOULD change without modifying code. `composer rector:apply` actually performs the changes. ### Rules 1. **Default workflow is dry-run.** Never run `composer rector:apply` outside a scoped reduction sprint. Mass-applying produces unreviewable PRs. 2. **One rule-set per sprint.** Pick `SetList::DEAD_CODE` (or similar) for one PR. Apply, review, regenerate baselines, commit. Then move to the next set. 3. **Run all tests + Larastan after each apply.** Rector is deterministic but rule-set interactions can produce surprises (e.g., `TYPE_DECLARATION` may surface new Larastan errors that were previously hidden by dynamic typing). ## Currently configured rule sets PHP language: - `withPhpSets(php82: true)` — language features up to PHP 8.2 Quality: - `SetList::CODE_QUALITY` - `SetList::DEAD_CODE` - `SetList::EARLY_RETURN` - `SetList::TYPE_DECLARATION` - `SetList::PRIVATIZATION` Laravel: - `LaravelSetList::LARAVEL_CODE_QUALITY` - `LaravelSetList::LARAVEL_COLLECTION` **Not yet enabled** (deferred to specific reduction sprints): - `LaravelLevelSetList::UP_TO_LARAVEL_*` — disruptive bulk upgrades - `SetList::NAMING` — reformats variable names; high churn - `SetList::INSTANCEOF` — substantial logic changes Add a set during a reduction sprint by editing `rector.php` and running `composer rector` (dry-run) before applying. ## Adding skip-rules If a specific rule produces incorrect changes for the project, add to `withSkip([...])` in `rector.php`: ```php ->withSkip([ SomeSpecificRule::class => [ __DIR__ . '/app/path/to/file.php', ], ]) ``` Document the skip with a code comment in `rector.php` explaining why the rule is bypassed for that path. ## Relationship to Larastan Different concerns: - **Larastan**: "this code is wrong" (types, null-safety, missing methods) - **Rector**: "this code can be modernised" (PHP version idioms, Laravel idioms, dead code, early-return patterns) Both run on the same codebase. After a Rector apply-sprint, regenerate the Larastan baseline — Rector changes often resolve Larastan errors automatically. ## CI integration Not enabled yet. When added, `composer rector` (dry-run) becomes a non-blocking PR comment that surfaces suggested modernisations. Apply happens manually, never automatically in CI.