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>
This commit is contained in:
@@ -12,6 +12,14 @@ Design document: `/dev-docs/design-document.md`
|
||||
- Frontend: TypeScript, Vue 3 (Composition API), Vuexy/Vuetify, Pinia, TanStack Query
|
||||
- Testing: PHPUnit (backend), Vitest (frontend)
|
||||
|
||||
## Quality gates
|
||||
|
||||
- `php artisan test` — PHPUnit feature suite. See Testing rules below.
|
||||
- `./vendor/bin/pint` — code style. Runs pre-commit in scope; format before merge.
|
||||
- `composer analyse` — Larastan static analysis at level 6 with
|
||||
accept-all baseline. New errors beyond the baseline must be fixed
|
||||
before merge. See `/dev-docs/LARASTAN.md`.
|
||||
|
||||
## Repository layout
|
||||
|
||||
- `api/` — Laravel backend
|
||||
|
||||
1
api/.gitignore
vendored
1
api/.gitignore
vendored
@@ -17,6 +17,7 @@
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/storage/app/phpstan-tmp
|
||||
/storage/pail
|
||||
/vendor
|
||||
Homestead.json
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.23",
|
||||
"larastan/larastan": "^3.0",
|
||||
"laravel/pail": "^1.2.2",
|
||||
"laravel/pint": "^1.24",
|
||||
"laravel/sail": "^1.41",
|
||||
@@ -55,6 +56,9 @@
|
||||
"@php artisan config:clear --ansi",
|
||||
"@php artisan test"
|
||||
],
|
||||
"analyse": "vendor/bin/phpstan analyse --memory-limit=2G",
|
||||
"analyse:baseline": "vendor/bin/phpstan analyse --generate-baseline --memory-limit=2G",
|
||||
"analyse:clear-cache": "vendor/bin/phpstan clear-result-cache",
|
||||
"post-autoload-dump": [
|
||||
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
|
||||
"@php artisan package:discover --ansi"
|
||||
|
||||
186
api/composer.lock
generated
186
api/composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "162fa15c2d2ac177259583cf0b271a30",
|
||||
"content-hash": "4c61afc38c9aea624f684146a9b0719a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
@@ -7765,6 +7765,137 @@
|
||||
},
|
||||
"time": "2025-04-30T06:54:44+00:00"
|
||||
},
|
||||
{
|
||||
"name": "iamcal/sql-parser",
|
||||
"version": "v0.7",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/iamcal/SQLParser.git",
|
||||
"reference": "610392f38de49a44dab08dc1659960a29874c4b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/iamcal/SQLParser/zipball/610392f38de49a44dab08dc1659960a29874c4b8",
|
||||
"reference": "610392f38de49a44dab08dc1659960a29874c4b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"php-coveralls/php-coveralls": "^1.0",
|
||||
"phpunit/phpunit": "^5|^6|^7|^8|^9"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"iamcal\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cal Henderson",
|
||||
"email": "cal@iamcal.com"
|
||||
}
|
||||
],
|
||||
"description": "MySQL schema parser",
|
||||
"support": {
|
||||
"issues": "https://github.com/iamcal/SQLParser/issues",
|
||||
"source": "https://github.com/iamcal/SQLParser/tree/v0.7"
|
||||
},
|
||||
"time": "2026-01-28T22:20:33+00:00"
|
||||
},
|
||||
{
|
||||
"name": "larastan/larastan",
|
||||
"version": "v3.9.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/larastan/larastan.git",
|
||||
"reference": "9ad17e83e96b63536cb6ac39c3d40d29ff9cf636"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/larastan/larastan/zipball/9ad17e83e96b63536cb6ac39c3d40d29ff9cf636",
|
||||
"reference": "9ad17e83e96b63536cb6ac39c3d40d29ff9cf636",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"iamcal/sql-parser": "^0.7.0",
|
||||
"illuminate/console": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/container": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/contracts": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/database": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/http": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/pipeline": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"illuminate/support": "^11.44.2 || ^12.4.1 || ^13",
|
||||
"php": "^8.2",
|
||||
"phpstan/phpstan": "^2.1.44"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^13",
|
||||
"laravel/framework": "^11.44.2 || ^12.7.2 || ^13",
|
||||
"mockery/mockery": "^1.6.12",
|
||||
"nikic/php-parser": "^5.4",
|
||||
"orchestra/canvas": "^v9.2.2 || ^10.0.1 || ^11",
|
||||
"orchestra/testbench-core": "^9.12.0 || ^10.1 || ^11",
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0.1",
|
||||
"phpunit/phpunit": "^10.5.35 || ^11.5.15 || ^12.5.8"
|
||||
},
|
||||
"suggest": {
|
||||
"orchestra/testbench": "Using Larastan for analysing a package needs Testbench",
|
||||
"phpmyadmin/sql-parser": "Install to enable Larastan's optional phpMyAdmin-based SQL parser automatically"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
"phpstan": {
|
||||
"includes": [
|
||||
"extension.neon"
|
||||
]
|
||||
},
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Larastan\\Larastan\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Can Vural",
|
||||
"email": "can9119@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan extension for Laravel",
|
||||
"keywords": [
|
||||
"PHPStan",
|
||||
"code analyse",
|
||||
"code analysis",
|
||||
"larastan",
|
||||
"laravel",
|
||||
"package",
|
||||
"php",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/larastan/larastan/issues",
|
||||
"source": "https://github.com/larastan/larastan/tree/v3.9.6"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/canvural",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-16T10:02:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laravel/pail",
|
||||
"version": "v1.2.4",
|
||||
@@ -8334,6 +8465,59 @@
|
||||
},
|
||||
"time": "2022-02-21T01:04:05+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.51",
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/dc3b523c45e714c70de2ac5113b958223b55dc59",
|
||||
"reference": "dc3b523c45e714c70de2ac5113b958223b55dc59",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
},
|
||||
"bin": [
|
||||
"phpstan",
|
||||
"phpstan.phar"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"files": [
|
||||
"bootstrap.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "PHPStan - PHP Static Analysis Tool",
|
||||
"keywords": [
|
||||
"dev",
|
||||
"static analysis"
|
||||
],
|
||||
"support": {
|
||||
"docs": "https://phpstan.org/user-guide/getting-started",
|
||||
"forum": "https://github.com/phpstan/phpstan/discussions",
|
||||
"issues": "https://github.com/phpstan/phpstan/issues",
|
||||
"security": "https://github.com/phpstan/phpstan/security/policy",
|
||||
"source": "https://github.com/phpstan/phpstan-src"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/ondrejmirtes",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/phpstan",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2026-04-21T18:22:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
"version": "11.0.12",
|
||||
|
||||
7477
api/phpstan-baseline.neon
Normal file
7477
api/phpstan-baseline.neon
Normal file
File diff suppressed because it is too large
Load Diff
19
api/phpstan.neon
Normal file
19
api/phpstan.neon
Normal file
@@ -0,0 +1,19 @@
|
||||
includes:
|
||||
- vendor/larastan/larastan/extension.neon
|
||||
- phpstan-baseline.neon
|
||||
|
||||
parameters:
|
||||
paths:
|
||||
- app/
|
||||
- database/
|
||||
- tests/
|
||||
level: 6
|
||||
|
||||
excludePaths:
|
||||
- bootstrap/cache/*
|
||||
- storage/*
|
||||
- vendor/*
|
||||
|
||||
checkModelProperties: true
|
||||
|
||||
tmpDir: storage/app/phpstan-tmp
|
||||
@@ -747,5 +747,144 @@ externe lijsten nog niet compleet zijn.
|
||||
|
||||
---
|
||||
|
||||
## Larastan reduction sprints
|
||||
|
||||
Larastan (PHPStan for Laravel) is geïnstalleerd op level 6 met een
|
||||
accept-all baseline van 1556 errors over 678 files (41 distinct
|
||||
identifiers). Zie `/dev-docs/LARASTAN.md` voor werkmodel. Per-categorie
|
||||
reduction-sprints hieronder — elke sprint mikt op één identifier, laat
|
||||
de baseline krimpen en regenereert hem aan het einde.
|
||||
|
||||
### TECH-LARASTAN-01 — property.notFound
|
||||
|
||||
**Priority:** Middel (post-foundation, incremental)
|
||||
**Scope:** baseline-entries met identifier `property.notFound`.
|
||||
**Estimate:** 613 errors over 87 files.
|
||||
**Completion gate:** category count daalt naar 0 in geregenereerde
|
||||
baseline; volledige test suite groen.
|
||||
|
||||
**Approach:**
|
||||
- Merendeel zit op Eloquent-modellen waar `$user->id` of vergelijkbaar
|
||||
niet door PHPDoc wordt herkend — los op door `@property` annotaties
|
||||
op modellen toe te voegen (of via `php artisan ide-helper:models`
|
||||
als dat acceptabel wordt gevonden).
|
||||
- Commit per sub-directory als >50 errors.
|
||||
|
||||
### TECH-LARASTAN-02 — missingType.generics
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** baseline-entries met identifier `missingType.generics`.
|
||||
**Estimate:** 289 errors over 52 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Zit vooral op factories (`extends Factory<Model>`) en
|
||||
`HasFactory`-gebruik zonder template. Voeg type-params toe aan
|
||||
class-declaraties en docblocks.
|
||||
- Overlapt deels met TYPE_DECLARATION-sprint van Rector.
|
||||
|
||||
### TECH-LARASTAN-03 — argument.templateType
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** baseline-entries met identifier `argument.templateType`.
|
||||
**Estimate:** 154 errors over 31 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Voornamelijk `collect(...)` calls waar PHPStan de generieke
|
||||
template TKey/TValue niet kan resolven. Typeer de input expliciet
|
||||
of gebruik `Collection::make([...])` met generieke annotatie.
|
||||
|
||||
### TECH-LARASTAN-04 — missingType.iterableValue
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** baseline-entries met identifier `missingType.iterableValue`.
|
||||
**Estimate:** 98 errors over 61 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Methode-return-types als `array` zonder value-type. Voeg
|
||||
`array<string, mixed>` of specifieker toe aan form-requests,
|
||||
resource `toArray()` methods, factory `definition()` methods.
|
||||
|
||||
### TECH-LARASTAN-05 — argument.type
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** baseline-entries met identifier `argument.type`.
|
||||
**Estimate:** 77 errors over 32 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Reële type-mismatches (bijv. string doorgegeven waar `'strict'|'lax'`
|
||||
vereist is). Case-by-case reviewen — niet mechanisch.
|
||||
|
||||
### TECH-LARASTAN-06 — method.notFound
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** baseline-entries met identifier `method.notFound`.
|
||||
**Estimate:** 50 errors over 26 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Meestal "Call to an undefined method Illuminate\\…::users()" —
|
||||
relationship methods die PHPStan niet kent. Los op via
|
||||
`@method` annotaties of generieke relationship-return types.
|
||||
|
||||
### TECH-LARASTAN-07 — method.childReturnType
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** baseline-entries met identifier `method.childReturnType`.
|
||||
**Estimate:** 35 errors over 35 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Eén-op-één met factory `definition()` methodes. Smeedt samen met
|
||||
TECH-LARASTAN-02 in één sprint indien praktisch.
|
||||
|
||||
### TECH-LARASTAN-08 — method.unresolvableReturnType
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** baseline-entries met identifier
|
||||
`method.unresolvableReturnType`.
|
||||
**Estimate:** 32 errors over 9 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
### TECH-LARASTAN-09 — assign.propertyType
|
||||
|
||||
**Priority:** Middel (reële type-bug kans hoger dan bij generics)
|
||||
**Scope:** baseline-entries met identifier `assign.propertyType`.
|
||||
**Estimate:** 31 errors over 10 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Meestal Carbon vs string mismatch op Eloquent properties —
|
||||
modelcasts goed zetten zodat Eloquent de datetime teruggeeft waar
|
||||
hij beloofd is.
|
||||
|
||||
### TECH-LARASTAN-10 — instanceof.alwaysTrue
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** baseline-entries met identifier `instanceof.alwaysTrue`.
|
||||
**Estimate:** 28 errors over 17 files.
|
||||
**Completion gate:** category count naar 0; tests groen.
|
||||
|
||||
**Approach:**
|
||||
- Dead `instanceof`-checks. Prefab voor Rector's `DEAD_CODE`
|
||||
sprint — wachten of combineren.
|
||||
|
||||
### TECH-LARASTAN-CI — CI integration
|
||||
|
||||
**Priority:** Middel
|
||||
**Scope:** wire `composer analyse` als blokkerende PR-gate in CI.
|
||||
**Depends on:** CI-infrastructuurkeuze.
|
||||
|
||||
### TECH-LARASTAN-L8 — level 8 migration
|
||||
|
||||
**Priority:** Laag
|
||||
**Scope:** niveau 6→8 verhogen nadat level-6 baseline op 0 staat.
|
||||
**Estimate:** onbekend totdat level 6 leeg is.
|
||||
|
||||
---
|
||||
|
||||
_Laatste update: April 2026_
|
||||
_Voeg nieuwe items toe met prefix: ARCH-, COMM-, OPS-, VOL-, ART-, FORM-, SUP-, DIFF-, APPS-, TECH-, UX-_
|
||||
|
||||
52
dev-docs/LARASTAN.md
Normal file
52
dev-docs/LARASTAN.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 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.
|
||||
Reference in New Issue
Block a user