Filed by the skills lane seat (session session_01LraLgQVGq8egUwfYZpbYt1) on behalf of the dev that delivered PR #14672 (#14616), whose own dedup could not be validated in its container (repo-scoped REST 403, the MCP control search rate-limited). The seat's targeted MCP search on this axis returned 0 results with incomplete_results: false. Unassigned, ⛔ not graded, ⛔ no pm:queue — observation class.
What
Inside selfTest() in scripts/pm/dispatch-gates.mjs (measured at origin/main2aa8456c):
const relative = [...].join('\n') at :11023 — function scope — binds a fixture STRING to the name node:path exports as a function;- a
const resolve = () => ... in a nested block does the same for resolve.
Any case written later in that function that calls relative() or resolve() expecting node:path gets a run-time TypeError: relative is not a function. The shadowing is invisible at parse time, so node --check passes and the first signal is a dead battery.
Measured cost
#14616's first self-test battery on its branch died on exactly this (TypeError: relative is not a function), one full run of the 1,240-case battery under the shared verify lock (~4 minutes plus the lock wait). The delivered fix (commit da479d10) works around it by taking the repo-relative spelling from ROOT instead of calling relative, and records in its own comment that relative and resolve are the only two node:path names shadowed anywhere in the function.
Why it is a finding, not a card
Loud rather than silent: the self-test IS the gate, so a shadowed call fails the battery instead of passing a bad reading. Nothing on main is red. The cost is one wasted battery per future case that reaches for either name, which is a contributor-time class, not a correctness class.
Shape of a fix, not prescribed
Rename the two fixture bindings (they are local test data), or import node:path as a namespace in this module so the function-scope names cannot collide. scripts/pm/** is governed surface — draft PR + human merge if anyone takes it. ⛔ Not folded into #14672, which is fenced to one self-test case.
Refs: #14616 · PR #14672 (da479d10, the working-around commit and the comment that measured the two names).
Filed by the skills lane seat (session
session_01LraLgQVGq8egUwfYZpbYt1) on behalf of the dev that delivered PR #14672 (#14616), whose own dedup could not be validated in its container (repo-scoped REST 403, the MCP control search rate-limited). The seat's targeted MCP search on this axis returned 0 results withincomplete_results: false. Unassigned, ⛔ not graded, ⛔ nopm:queue— observation class.What
Inside
selfTest()inscripts/pm/dispatch-gates.mjs(measured atorigin/main2aa8456c):const relative = [...].join('\n')at:11023— function scope — binds a fixture STRING to the namenode:pathexports as a function;const resolve = () => ...in a nested block does the same forresolve.Any case written later in that function that calls
relative()orresolve()expectingnode:pathgets a run-timeTypeError: relative is not a function. The shadowing is invisible at parse time, sonode --checkpasses and the first signal is a dead battery.Measured cost
#14616's first self-test battery on its branch died on exactly this (
TypeError: relative is not a function), one full run of the 1,240-case battery under the shared verify lock (~4 minutes plus the lock wait). The delivered fix (commitda479d10) works around it by taking the repo-relative spelling fromROOTinstead of callingrelative, and records in its own comment thatrelativeandresolveare the only twonode:pathnames shadowed anywhere in the function.Why it is a finding, not a card
Loud rather than silent: the self-test IS the gate, so a shadowed call fails the battery instead of passing a bad reading. Nothing on
mainis red. The cost is one wasted battery per future case that reaches for either name, which is a contributor-time class, not a correctness class.Shape of a fix, not prescribed
Rename the two fixture bindings (they are local test data), or import
node:pathas a namespace in this module so the function-scope names cannot collide.scripts/pm/**is governed surface — draft PR + human merge if anyone takes it. ⛔ Not folded into #14672, which is fenced to one self-test case.Refs: #14616 · PR #14672 (
da479d10, the working-around commit and the comment that measured the two names).