chore: install rector with accept-current-state baseline

Installs rector/rector ^2.0 (v2.4.2) + driftingly/rector-laravel
^2.0 as dev-dependencies. Configures PHP 8.2 language sets + safe
quality rule sets (CODE_QUALITY, DEAD_CODE, EARLY_RETURN,
TYPE_DECLARATION, PRIVATIZATION) + Laravel-specific sets
(LARAVEL_CODE_QUALITY, LARAVEL_COLLECTION).

Dry-run baseline: 487 rule-applications across 357 files. NO
changes applied in this commit — adoption is incremental via per-
set sprints documented in BACKLOG.md.

Top rules by volume:
  103  AddClosureVoidReturnTypeWhereNoReturnRector
   71  AddArrowFunctionReturnTypeRector
   51  AppToResolveRector
   34  ConvertStaticToSelfRector
   27  ReadOnlyClassRector
   18  NullToStrictStringFuncCallArgRector
   16  ReturnBinaryOrToEarlyReturnRector
   16  MakeModelAttributesAndScopesProtectedRector
   13  RemoveUnusedVariableAssignRector
   13  OptionalToNullsafeOperatorRector
   13  FlipTypeControlToUseExclusiveTypeRector

Composer scripts:
  - composer rector              — DRY-RUN (default)
  - composer rector:apply        — apply changes
  - composer rector:clear-cache  — clear Rector cache

Dry-run exits with code 2 when suggestions exist (Rector convention,
not an error state). Apply-mode exits 0 on clean runs.

Documentation: /dev-docs/RECTOR.md added; CLAUDE.md updated.

Backlog: per-set application sprints seeded
(TECH-RECTOR-01..05 + TECH-RECTOR-CI). DEAD_CODE (smallest scope)
and TYPE_DECLARATION (biggest volume, will help reduce Larastan
baseline) are the natural first two.

Disruptive sets deliberately deferred:
  - LaravelLevelSetList::UP_TO_LARAVEL_* — broad bulk upgrades
  - SetList::NAMING — high-churn variable renames
  - SetList::INSTANCEOF — substantial logic changes

Memory limit 2G (dry-run completed within it).

No production behavior change. No code modified — Rector ran
dry-run only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 03:50:41 +02:00
parent 7542808cab
commit a043b88bc0
7 changed files with 384 additions and 2 deletions

View File

@@ -886,5 +886,86 @@ baseline; volledige test suite groen.
---
## Rector application sprints
Rector is geïnstalleerd en geconfigureerd op PHP 8.2 + safe quality
+ Laravel code-quality rule sets. Dry-run rapporteert **487
rule-applications over 357 files** verdeeld over ~35 distinct rules.
Zie `/dev-docs/RECTOR.md` voor werkmodel. Per-ruleset sprints
hieronder — elke sprint beperkt zich tot één scope, past toe,
verifieert tests + Larastan, regenereert waar nodig.
### TECH-RECTOR-01 — DEAD_CODE sprint
**Priority:** Middel
**Scope:** `SetList::DEAD_CODE` over app/, database/, tests/.
**Estimate:** Top 13 unused-variable removals via
`RemoveUnusedVariableAssignRector`, plus verwante dead-code rules.
Exact totaal: ~30-50 changes.
**Completion gate:** `composer rector:apply` clean voor deze set;
test suite groen; Larastan baseline geregenereerd en kleiner (of
gelijk). Commit per sub-directory indien >50 wijzigingen.
**Approach:**
- Tijdelijk in rector.php alleen DEAD_CODE aanzetten, andere sets
uitcommentariseren.
- `composer rector` om diff te reviewen voor zekerheid.
- `composer rector:apply`.
- `composer test` + `composer analyse`.
- Herstel rector.php naar volledige config.
- Commit.
### TECH-RECTOR-02 — TYPE_DECLARATION sprint
**Priority:** Middel (hoogste volume — 174+ changes)
**Scope:** `SetList::TYPE_DECLARATION`.
**Estimate:** ~174+ changes — top drivers:
`AddClosureVoidReturnTypeWhereNoReturnRector` (103),
`AddArrowFunctionReturnTypeRector` (71), plus
`AddArrayFunctionClosureParamTypeRector` en kleinere.
**Completion gate:** zie TECH-RECTOR-01. **Extra**: deze set lost
waarschijnlijk veel `missingType.*` errors in Larastan baseline op —
regenereer en commit gereduceerde phpstan-baseline.neon mee.
### TECH-RECTOR-03 — LARAVEL_CODE_QUALITY + LARAVEL_COLLECTION sprint
**Priority:** Middel
**Scope:** `LaravelSetList::LARAVEL_CODE_QUALITY` +
`LaravelSetList::LARAVEL_COLLECTION`.
**Estimate:** ~80 changes — `AppToResolveRector` (51),
`DispatchToHelperFunctionsRector` (8),
`EloquentOrderByToLatestOrOldestRector` (7),
`CarbonToDateFacadeRector` (4), plus collection-idioms.
**Completion gate:** zie TECH-RECTOR-01.
**Approach:**
- Splits in twee commits (één per set) als het totaal te groot is
om in één review te laten passen.
### TECH-RECTOR-04 — CODE_QUALITY + EARLY_RETURN + PRIVATIZATION
**Priority:** Laag
**Scope:** resterende quality-sets (~80 changes).
**Estimate:** `ConvertStaticToSelfRector` (34),
`ReadOnlyClassRector` (27), `ReturnBinaryOrToEarlyReturnRector` (16),
`ClosureToArrowFunctionRector` (9), etc.
**Completion gate:** zie TECH-RECTOR-01.
### TECH-RECTOR-05 — Laravel modernisation sprint
**Priority:** Laag
**Scope:** review en selectief enable van
`LaravelLevelSetList::UP_TO_LARAVEL_*` in rector.php.
**Estimate:** onbekend tot per-set dry-runs zijn bekeken.
**Completion gate:** per-set applicatie als gescoopte commits.
### TECH-RECTOR-CI — CI integration
**Priority:** Laag
**Scope:** `composer rector` (dry-run) als PR-comment-surface. Apply
blijft handmatig.
---
_Laatste update: April 2026_
_Voeg nieuwe items toe met prefix: ARCH-, COMM-, OPS-, VOL-, ART-, FORM-, SUP-, DIFF-, APPS-, TECH-, UX-_

94
dev-docs/RECTOR.md Normal file
View File

@@ -0,0 +1,94 @@
# 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.