Why does it matter if your linter and static analyzer agree across repositories? Because the moment they don't, every developer has to remember which repo they're standing in before they trust the tool.
Pint gets this right across the fleet. api-license, api-server, and merchants all ship the identical pint.json:
// pint.json
{
"preset": "laravel",
"rules": {
"declare_strict_types": true,
"class_attributes_separation": {
"elements": {
"const": "none",
"property": "none",
"method": "one",
"trait_import": "none"
}
}
}
}
Run vendor/bin/pint in any of them and you get the same formatting decisions. A developer who's fixed a Pint complaint in one repo has fixed it everywhere, because the config didn't change underneath them.
PHPStan is the honest counterexample, worth stating plainly instead of pretending it isn't there. api-license and api-server run at level 9. merchants runs at level 5, with its own separate list of ignored error patterns. Same analyzer, same fleet, two different bars for what counts as clean. merchants is a larger, older app and api-license is a small leaf service, so the gap has a reason, but a developer moving between repositories still can't assume silence means the same thing everywhere.
Consistent tooling isn't a nice-to-have. It's what lets a developer trust a green check without re-deriving what that check actually verified.
Reviewing Code Without Relitigating Style
Here's what kills code review velocity faster than bad code: good code that triggers an argument about formatting.
composer run format # ./vendor/bin/pint
composer run check # ./vendor/bin/phpstan analyse --memory-limit=2G
composer run test # ./vendor/bin/pest
Three commands, run before you ask anyone to look at your diff. Pint decides spacing and brace placement. PHPStan decides whether the types hold. Pest, including ArchTest.php, decides whether the change follows the structural conventions, Job suffixes, final invokable actions, strict types everywhere. None of that needs a human eye.
What's left for the human reviewer is the only thing a human should review: does this solve the right problem, and does the logic do what it claims. A reviewer spending attention on tab width instead of logic isn't being careful, they're spending a scarce resource on something a machine already checked for free. Automate the argument you'd otherwise have every week, and you get back the one that matters.
Recap
- [X] First hour: a README stating route and test counts a newcomer can verify, not prose they have to trust
- [X] Setup: one command, not a checklist someone will get half right
- [X] Conventions: enforced by
arch()tests, not just described in a comment someone stopped reading - [X] Documentation: regenerated via
boost:update, not hand-maintained until it drifts - [X] Errors: every branch answers what happened and what to do about it
- [X] Tooling: the same
pint.jsoneverywhere; the PHPStan level gap is a known debt, not a hidden one - [X] Reviews: format, check, and test run before a human opens the diff
A codebase with good developer experience doesn't need a new developer to be told how it works. It tells them itself, in the first hour, and it keeps telling them the truth every hour after that.