Files
crewli/dev-docs/LARASTAN.md
bert.hausmans 7542808cab chore: install larastan at level 6 with accept-all baseline
Installs larastan/larastan ^3.0 (v3.9.6) as a dev-dependency. Level
6 is the starting target — catches missing typehints, method-
existence, null-safety, and model-property existence. Level 8
deferred to a follow-up sprint after level-6 baseline reaches zero.

Baseline error count at install: 1556 errors across 678 analysed
files (41 distinct identifiers).

Top 10 identifiers (errors / files):
  613 /  87  property.notFound
  289 /  52  missingType.generics
  154 /  31  argument.templateType
   98 /  61  missingType.iterableValue
   77 /  32  argument.type
   50 /  26  method.notFound
   35 /  35  method.childReturnType
   32 /   9  method.unresolvableReturnType
   31 /  10  assign.propertyType
   28 /  17  instanceof.alwaysTrue

Composer scripts:
  - composer analyse              — run static analysis
  - composer analyse:baseline     — regenerate baseline
  - composer analyse:clear-cache  — clear PHPStan result cache

Config deviation from plan: checkGenericClassInNonGenericObjectType
was removed in PHPStan 2.x (which Larastan 3 bundles) — setting
dropped from phpstan.neon, otherwise config matches the work
package verbatim. Defaults cover the original intent.

Documentation: /dev-docs/LARASTAN.md added; CLAUDE.md quality-gates
section introduced (with PHPUnit + Pint + Larastan listed).

Backlog: /dev-docs/BACKLOG.md gets 10 per-identifier reduction
sprints (TECH-LARASTAN-01..10) seeded from the actual baseline top
categories, plus TECH-LARASTAN-CI and TECH-LARASTAN-L8 follow-ups.

Memory limit 2G (baseline generation completed within it).

No production behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 03:46:27 +02:00

53 lines
1.7 KiB
Markdown

# Larastan (PHPStan for Laravel)
Static analysis for the Crewli backend. Configured at level 6 with
an accept-all baseline.
## Running locally
- `composer analyse` — run static analysis. Suppresses baselined errors.
- `composer analyse:baseline` — regenerate the baseline. Use after a
reduction sprint to lock in the new lower-debt state.
- `composer analyse:clear-cache` — clear PHPStan result cache.
Memory: 2G default. Bump to 4G in `composer.json` if you hit OOM.
## The accept-all baseline model
`phpstan-baseline.neon` is a time-snapshot of every error that existed
when Larastan was first installed. Errors in the baseline are
suppressed; Larastan reports only errors NOT in the baseline.
### Rules
1. **New code must not introduce new errors.** Fix them before merge.
Do NOT regenerate the baseline to absorb new errors.
2. **Refactoring that REMOVES baseline errors is good.** Regenerate
the baseline (`composer analyse:baseline`) so the file reflects
the new lower-debt reality. Commit alongside the refactor.
3. **Reduction sprints REPLACE baseline entries with fixes.** See
`/dev-docs/BACKLOG.md` for sprint items.
## Current target
Level 6. Catches:
- missing typehints
- method existence
- null-safety on common paths
- Laravel model property existence
Level 8 is the eventual target — deferred until level 6 baseline
reaches zero.
## Adding exclusions
Do NOT add blanket `ignoreErrors` patterns to `phpstan.neon`. False
positives get a code-level `@phpstan-ignore-next-line` comment with
upstream-issue justification. Pattern-level ignores rot fast.
## CI integration
Not enabled yet. When added, `composer analyse` is a blocking PR
gate. The "new code must not introduce new errors" rule is only
enforceable with CI.