stx typecheck reports diagnostics for <script server> and <script client> blocks but skips a bare <script> entirely. Since a bare <script> is the server block — it is what most components in storage/framework/defaults actually use — this means the most common block form in the ecosystem is unchecked.
Repro
Three files, byte-identical except for the opening tag:
<!-- bare.stx -->
<script>
const broken = (((
</script>
<div>hi</div>$ stx typecheck bare.stx
Checked 0 script block(s) and 0 template expression(s) in 0 file(s) — 0 error(s), 0 warning(s)
$ stx typecheck server.stx # same content, <script server>
Checked 1 script block(s) and 0 template expression(s) in 1 file(s) — 1 error(s), 0 warning(s)
$ stx typecheck client.stx # same content, <script client>
Checked 1 script block(s) and 0 template expression(s) in 1 file(s) — 1 error(s), 0 warning(s)On a real component the file is still counted, but the block is not — Checked 0 script block(s) and 12 template expression(s) in 1 file(s) for a file that plainly has one script block.
stx 0.2.175.
Why this matters
This is not hypothetical. storage/framework/defaults shipped 18 script blocks that could not parse, across many releases, and typecheck reported only 2 of them — precisely the two in <script client> blocks. The other 16 were bare <script> and were invisible:
// Marketing/Feature.stx, as shipped
const { className = '', feature = {, isActive = false } = defineProps<FeatureProps>()
name: '',
summary: '',
...
}Sixteen components were dead on arrival for anyone scaffolding from defaults, and the tool whose job is to catch that reported success. Fixed in stacksjs/stacks@f2fdb53, but the reason it went unnoticed is this gap.
Expected
A bare <script> should be checked exactly as <script server> is — they are the same thing. If there is a deliberate reason to skip it, the summary should say the block was skipped rather than counting it as zero, because "0 errors" over an unchecked block reads as a pass.
Related: the same "reports success while measuring nothing" family as #1906 (--lib silencing every diagnostic) and #1911 (prohibited APIs matched inside comments).