Summary
fragmentNeedsRuntime (the #1809 handoff gate) fails to detect a fragment that needs the runtime when its reactivity is expressed as bare directives / interpolation on plain elements — so on a runtime-less page, no full-load handoff happens and the fragment's hydration dies silently.
The gate
packages/router/src/client.ts:
function fragmentNeedsRuntime(frag){
return frag.indexOf('__stx_setup_')!==-1
||frag.indexOf('data-stx-scope=')!==-1
||frag.indexOf('data-stx-reactive')!==-1
||/=\s*window\.stx\s*;/.test(frag);
}It keys on scope/setup/reactive markers only.
Repro
fragmentNeedsRuntime('<div @click="x()">{{ y }}</div>') // → false (MISS)A fragment whose only dynamic bits are @click (to a global handler), , x-model, :attr, :if, etc. — with no data-stx-scope= / __stx_setup_ / data-stx-reactive in the emitted HTML — is reported as not needing the runtime.
Impact
When window.stx hasn't loaded yet (you landed on a static page first) and you SPA-navigate to such a fragment, fragmentNeedsRuntime returns false → no handoff to a full load → the runtime never initializes → the directives/interpolation never bind, with no console error. This is the same failure class #1809 fixed, just an uncovered input shape.
Suggested fix
Extend the sniff to also detect bare directives/interpolation:
{{(interpolation)@-prefixed event handlers (@click,@input, …):-prefixed bindings on attributesx-directives (x-model,x-class,x-if, …)
Or, more robustly: when window.stx is absent, hand off to a full load whenever the fragment contains any dynamic marker, rather than enumerating a subset.