Filed unassigned by the dev seat porting this gate to objectui (objectui#6092, branch claude/issue-6092-entry-guard-gate, session session_019b5UBNMtTzKbVtZZGvFuxe). Out of that card's scope — recording it, not acting on it.
What was measured
On 644ad5043, driving this repository's own scripts/check-entry-guard.mjs directly:
upstream scanFile findings for the percent-encoding spelling: 0
upstream scanFile findings for the plain spelling: 1
The two inputs were:
if(import.meta.url===`file://${process.argv[1]}`){main();}// → 0 findingsif(process.argv[1]===x){}// → 1 findingSo a hand-typed entry guard written inside a template literal is invisible to the gate, and lands green.
Why
codeOnly() masks comment || literal, and js-comment-mask.mjs's scanSource reports an interpolation's bytes as the enclosing template's literal content. That is its documented contract and it is the right answer for its other callers — a process.argv[1] inside a string payload for a spawned child is not a guard, which run-with-stall-guard.mjs:607 relies on. But it makes ${...} — which the language executes — prose as far as this gate is concerned.
Why it matters more than the shape suggests
`file://${process.argv[1]}` is not a hypothetical spelling. It is the one invoked-as.mjs's header singles out as the worst of the family, because it goes inert with no symlink involved at all: it percent-encodes apart from argv[1] in any directory whose name needs encoding. Measured in objectui in a directory named a#b c:
INERT file:///…/a%23b%20c/enc.mjs vs /…/a#b c/enc.mjs
The gate exists to stop the next spelling. This is the one spelling it cannot stop, and the failure is silent in the direction that matters: the gate reports a clean scan.
Not currently live here — git grep 'process.argv[1]' -- scripts/ on 644ad5043 returns only prose and one string payload, so nothing in this tree is written this way today. This is a hole in the gate, not an outage.
Measured in objectui, where the same tree is not yet swept: the straight port of this gate listed 28 of that repo's 29 hand-typed guards and omitted exactly the template-written one (scripts/check-node-esm-load.mjs:847).
The fix that was made downstream, for reference
objectui's port (PR objectui#6133) adds a third array to scanSource, interpolation, marking the bytes an interpolation contributes as code. comment and literal are unchanged, so every existing caller keeps the mask it had; a caller that wants the executed view subtracts. Two exclusions are load-bearing and are pinned there:
- the
${ and its closing } stay masked, so a caller counting brackets stays balanced; - a nested template's body inside the interpolation stays masked, because those bytes really are content.
The second is not theoretical. A first cut that un-masked the whole span put a nested interpolation's inner } into the outer span's interior while its ${ stayed masked, and the unmatched brace desynced check-entry-guard.mjs's top-level statement slicer badly enough that four files whose dispatch really is guarded were reported as running on import.
Whether this repository wants the same shape, a different one, or judges the hole acceptable given the tree is currently clean, is the call to make — this is a report, not a proposal.
Refs: objectui#6092 (the port) · objectui#6133 (the downstream fix) · objectstack#10427 (the last time scanSource's template handling cost something)
Generated by Claude Code
Filed unassigned by the dev seat porting this gate to objectui (objectui#6092, branch
claude/issue-6092-entry-guard-gate, sessionsession_019b5UBNMtTzKbVtZZGvFuxe). Out of that card's scope — recording it, not acting on it.What was measured
On
644ad5043, driving this repository's ownscripts/check-entry-guard.mjsdirectly:The two inputs were:
So a hand-typed entry guard written inside a template literal is invisible to the gate, and lands green.
Why
codeOnly()maskscomment || literal, andjs-comment-mask.mjs'sscanSourcereports an interpolation's bytes as the enclosing template's literal content. That is its documented contract and it is the right answer for its other callers — aprocess.argv[1]inside a string payload for a spawned child is not a guard, whichrun-with-stall-guard.mjs:607relies on. But it makes${...}— which the language executes — prose as far as this gate is concerned.Why it matters more than the shape suggests
`file://${process.argv[1]}`is not a hypothetical spelling. It is the oneinvoked-as.mjs's header singles out as the worst of the family, because it goes inert with no symlink involved at all: it percent-encodes apart fromargv[1]in any directory whose name needs encoding. Measured in objectui in a directory nameda#b c:The gate exists to stop the next spelling. This is the one spelling it cannot stop, and the failure is silent in the direction that matters: the gate reports a clean scan.
Not currently live here —
git grep 'process.argv[1]' -- scripts/on644ad5043returns only prose and one string payload, so nothing in this tree is written this way today. This is a hole in the gate, not an outage.Measured in objectui, where the same tree is not yet swept: the straight port of this gate listed 28 of that repo's 29 hand-typed guards and omitted exactly the template-written one (
scripts/check-node-esm-load.mjs:847).The fix that was made downstream, for reference
objectui's port (PR objectui#6133) adds a third array to
scanSource,interpolation, marking the bytes an interpolation contributes as code.commentandliteralare unchanged, so every existing caller keeps the mask it had; a caller that wants the executed view subtracts. Two exclusions are load-bearing and are pinned there:${and its closing}stay masked, so a caller counting brackets stays balanced;The second is not theoretical. A first cut that un-masked the whole span put a nested interpolation's inner
}into the outer span's interior while its${stayed masked, and the unmatched brace desyncedcheck-entry-guard.mjs's top-level statement slicer badly enough that four files whose dispatch really is guarded were reported as running on import.Whether this repository wants the same shape, a different one, or judges the hole acceptable given the tree is currently clean, is the call to make — this is a report, not a proposal.
Refs: objectui#6092 (the port) · objectui#6133 (the downstream fix) · objectstack#10427 (the last time
scanSource's template handling cost something)Generated by Claude Code