Skip to content

feat(cli): run the validation gate by default on compile#21

Merged
math3usmartins merged 1 commit into
0.3.xfrom
feat/safe-default-compile-gate
Jul 5, 2026
Merged

feat(cli): run the validation gate by default on compile#21
math3usmartins merged 1 commit into
0.3.xfrom
feat/safe-default-compile-gate

Conversation

@math3usmartins

Copy link
Copy Markdown
Member

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).

`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>
@math3usmartins math3usmartins merged commit ba8e706 into 0.3.x Jul 5, 2026
6 checks passed
@math3usmartins math3usmartins deleted the feat/safe-default-compile-gate branch July 5, 2026 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant