feat(cli): run the validation gate by default on compile#21
Merged
Conversation
`compile` now runs the same gate as `check` — the generic validators plus PHPStan over the compiled output — before emitting, and fails the build (writing nothing) when the gate reports an error. A type argument that names no real class, and every other PHPStan-detectable error, now fails at compile time instead of slipping through to runtime. The soundness comes from PHPStan's real autoloader visibility, so a genuine plain-`.php` domain class used as a type argument is never false-rejected — no `.php`-scanning or autoload-map machinery is added to the transpiler. `--no-check` skips the gate and compiles directly (the previous behavior), for a fast iteration build when the gate has already been run separately. `--no-phpstan` runs only the generic validators; a missing PHPStan degrades to a non-failing warning. The gate logic is extracted into a shared `CheckGate` that both commands run, behind a `Gate` interface, with a shared `RendererFactory`. A skip-when-unchanged marker was considered — to spare no-op rebuilds the PHPStan cost — but dropped as unsound: its content-hash key can only proxy the gate's true dependency set, and the proxy is strictly narrower. It cannot capture the PHPStan config's transitive includes or the autoload universe the emitted code references, so it could skip a gate that would now fail and re-emit rejected output silently. A slower-but-sound default beats a fast one that occasionally lies; fast warm rebuilds are deferred to a sound mechanism (reusing PHPStan's own result cache). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
compilenow runs the same gate ascheck— the generic validators plus PHPStan over the compiled output — before emitting, and fails the build (writing nothing) when the gate reports an error. A type argument that names no real class, and every other PHPStan-detectable error, now fails at compile time instead of slipping through to runtime. The soundness comes from PHPStan's real autoloader visibility, so a genuine plain-.phpdomain class used as a type argument is never false-rejected — no.php-scanning or autoload-map machinery is added to the transpiler.--no-checkskips the gate and compiles directly (the previous behavior), for a fast iteration build when the gate has already been run separately.--no-phpstanruns only the generic validators; a missing PHPStan degrades to a non-failing warning. The gate logic is extracted into a sharedCheckGatethat both commands run, behind aGateinterface, with a sharedRendererFactory.A skip-when-unchanged marker was considered — to spare no-op rebuilds the PHPStan cost — but dropped as unsound: its content-hash key can only proxy the gate's true dependency set, and the proxy is strictly narrower. It cannot capture the PHPStan config's transitive includes or the autoload universe the emitted code references, so it could skip a gate that would now fail and re-emit rejected output silently. A slower-but-sound default beats a fast one that occasionally lies; fast warm rebuilds are deferred to a sound mechanism (reusing PHPStan's own result cache).