dist/signals.js — the client runtime every stx page loads — ships with unconditional console.log calls. None are behind a debug flag.
grep -c "console.log(" node_modules/@stacksjs/stx/dist/signals.js
# 41A sample:
console.log('[stx] signals runtime loading');
console.log('[stx] entering IIFE');
console.log('[stx] signal.set:', value, '->', newValue, 'effects:', effects.size);
console.log('[stx] :if dispatch on', el.tagName, ifAttr + '="' + ... );
console.log('[stx] bindIfChain entry:', head.tagName, 'branches:', ...);
console.log('[stx] bindIfChain SKIPPED (head already bound):', ...);Checked on @stacksjs/stx 0.2.176. I looked for a guard around each one — a debug config read, a window.__stx_debug, anything — and found none: every [stx]-prefixed log in the file is unconditional.
Why it matters
signal.set logs on every state change. That is the hot path. A page with a few reactive inputs produces a log per keystroke; a :for over a list that updates produces one per mutation. The cost is not only noise — console.log of live object references keeps them reachable for devtools and is slow enough to show up when it runs per-keystroke.
It buries the app's own output. Any app debugging its own code now reads its logs through a stream of framework internals, and anything logged by the page is a needle in that. This is the part that actually cost us time — we lost a while scrolling past [stx] lines before realising they were not ours.
It is visible to end users. Anyone opening devtools on a production stx site sees the framework narrating its own binding decisions, including element tag names and attribute values.
Expected
Either strip these at build time, or gate them on an explicit opt-in — debug: true in stx.config.ts already exists as a concept and would be the natural switch. The messages are genuinely useful when you need them; bindIfChain SKIPPED (head already bound) is exactly what you would want while diagnosing a double-bind. They just should not be on by default.
A build-time strip is probably better than a runtime flag: it keeps the code readable and costs nothing at runtime.
Workaround
None that is good. An app can monkey-patch console.log to filter [stx], which is worse than the problem.