A composer.json edited by hand and a lock file regenerated on a different machine drift apart quietly, and the first symptom is usually a deploy installing something nobody expected.
composer validate --strict --no-check-publish
It checks that the JSON is well-formed, that the lock file matches the manifest, and — with --strict — warns about the things that are merely untidy, such as a missing license or a dependency listed in both require and require-dev. The lock-file check is the one worth the CI step: it fails the build when someone commits a manifest change without the matching lock.