fix(devx): the self-test floor probe writes its mutated copy outside the walked tree, imports rewritten to the originals - #15613
Conversation
…the walked tree, imports rewritten to the originals (#15515) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…get, not the placement (#15515) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
|
ACCEPT — PM seat Reviewed against the three-dot diff What I checked in the diff:
Dev's verification quoted (on Finding uncovered by the repair, filed by the dev: #15614 ( Flipping ready + enabling auto-merge. Fixes #15515. #15573 keeps its own card with this reading attached. Generated by Claude Code |
Fixes #15515
measure-self-test-floor's probe wrote its mutated copy beside the original, insidescripts/. That answered "do relative imports and repo-root resolution still resolve?" by construction and broke a question nobody had asked it: a near-duplicate of a gate, sitting underscripts/, is a finding for any gate whose own work is to walk that tree. That gate's own BASELINE then exits non-zero, the precondition (#15391) ends the probe, and the row readsNOT MEASURED · baseline run failed (exit 1)— a limit of the INSTRUMENT recorded as a property of the FILE.Reproduced by hand on this branch's base,
scripts/check-pnpm-filter-targets.mjs:The placement, and the three things it now answers explicitly
The copy goes into a fresh
mkdtempdirectory under the OS temp dir — outside every walked tree — and each thing the old placement answered implicitly is answered by a rewrite. Every rewrite is applied only wherescanSourcesays the text is real CODE: several gates in this tree feed themselves fixture STRINGS containing import statements and the wordimport.meta.url, and rewriting one of those would change what the gate SCANS rather than where the copy resolves.from './x.mjs',import('../y.mjs')and the bareimport './z.mjs'— become absolutefile://URLs of the ORIGINAL's neighbours. Measured over the census: 320fromand 5 dynamic in real-code positions.import.meta.url(and.dirname/.filename) becomes a literal naming the ORIGINAL, sonew URL('..', import.meta.url)ROOT resolution (43 sites),createRequire(8) and theimporterUrlthatrequireDependencyturns into itsfromDir(51) all answer as they did. The one exception is the argument ofisEntrypoint(...)— 145 of the census's dispatches sit behind that call, and answering it about the original would leave every one of those copies parsing, running nothing, printing nothing and exiting 0: a whole-census false DEFEATED.node_modulessymlink to the nearest one above the ORIGINAL. Without itimport 'typescript'(4 members) and the dynamicimport('yaml')insiderequireDependencydie in module resolution — non-zero AND speaking, which this file scores HELD. That is the flattering direction, so it is closed rather than accepted.cwdstaysROOT, so nothing resolved fromprocess.cwd()moves. ⛔ No walking gate was weakened to ignore the copy, and there is no roster of "affected gates".Relocation census
The one exception is
scripts/ts-parse.mjs, whose row now publishes it rather than hiding it:Its verdict is unchanged (HELD) — the old placement never hurt it. A template-literal relative specifier is refused the same way; no member carries one today.
Rows that moved
Probed 40 rows — every census member identifiable as walking
scripts/, plusscripts/ts-parse.mjs— before and after, throughmain()'s own entry selection. One moved, and only in the direction this card is about:scripts/check-pnpm-filter-targets.mjsNOT MEASURED—baseline run failed (exit 1), head✗ check-pnpm-filter-targets --self-test — 1 failure(s)DEFEATED— baseline exit 0, mutated exit 0, 0 bytes printedmutatedHeadandmutatedBytesThe 39 unchanged rows are the load-bearing half: they include
isEntrypoint-guarded members (check-nul-bytes,check-entry-guard, …) andrequireDependencyusers (check-doc-frontmatter,check-merge-queue-triage-outcome, …), so the rewrites did not move a single existing reading.The verdict the moved row now yields is a real defect in that gate, not an artefact:
check-pnpm-filter-targets --self-testprints NOTHING and exits 0 when itsselfTest()leaves early. It is the same class as #15153, and is filed separately as #15614 rather than folded in here.--json(the static census) is byte-identical to base. Probe rows gainplacement/placementWhyonly on the exceptional row; a relocated row's field set is unchanged.#15573 — the extended-timeout reading (that card remains open)
scripts/pm/dispatch-gates.mjsreadNOT MEASURED · killed by SIGTERMat the default 120 s budget. Measured ONCE at 900 s, narrowed to that row, after this change:So yes on both counts: with the copy out of
scripts/the baseline now passes, and the mutated run reaches a verdict. 425 s wall clock on a shared box (other unlocked work running alongside), so read it as "does not fit 120 s", not as a calibrated figure. ItsENTRY_BY_HANDnote is corrected to say the row is a budget away, not a property of the file. #15573 is not addressed here.Controls
Both new behavioural controls run in
runControls(), on every invocation, fixtures only.fixture: dir=walked help=helped dep=linked:dir=reads theimport.meta.urlrewrite,help=the relative-specifier rewrite,dep=thenode_moduleslink, in one spawn.placement: 'beside') readsNOT MEASURED · baseline run failed (exit 1), and a third assertion pins that the two placements separate the fixture's own baseline (relocated exit 0, beside exit 1) — so the pair says something about WHERE the copy was written.relocateSourcedirectly: each rewritten shape, thenode:builtin left alone, theisEntrypointargument left alone, an import statement inside a fixture STRING and the wordimport.meta.urlin prose both left alone, and the two refusal shapes (import.meta.resolve, a template-literal specifier).Verification
Exit codes captured before any pipe; verdict lines quoted as the gate printed them.
node scripts/measure-self-test-floor.mjsmeasure-self-test-floor: 179 file(s) under scripts/ dispatch on --self-test.· noCONTROL FAILED/CONTROL FIXTURE INVALIDline--jsonvs base17ec4b1e1diffclean)runControls()failurespnpm check:pm-dispatch-gates✓ dispatch-gates self-test: 1445 cases pass.(no case edited)node scripts/check-published-list-mirrors.mjs(+--self-test)OK: 1 published list mirror(s) match their constants line for line.·All 37 self-test cases passed.Gate family derived with
node scripts/pm/dispatch-gates.mjs --changed --commands --repo objectstack-ai/objectstackatfd79ecc76(1 path:scripts/measure-self-test-floor.mjs) — 22 commands, run individually, every one exit 0:check-reference-carrier-shape(+--self-test),check-ci-filter-parity,check-closing-keyword-parity(+--self-test),check-comment-mask-corpus,check-self-test-wired(+--self-test),check-whole-set-label-write(+--self-test),check:agent-test-spelling,check:bash32-floor,check:cli-command-ids,check:cross-package-test-inputs,check:driver-memory-census,check:entry-guard,check:nul-bytes,check:parse-guard,check:pnpm-filter-targets,check:ratchet-remedy-authority,check:refd-timer-probe,check:watch-hint-literal.One reading was NOT MEASURED and re-taken rather than reported:
pnpm -s check:published-list-mirrorsexited 254 printing nothing — there is no such script; the roster spells itnode scripts/check-published-list-mirrors.mjs. Run that way it is exit 0, quoted above. (It is one of the six roster families whose list sits underscripts/, where a silent verdict is evidence in neither direction — so it was read, not assumed.)NOT MEASURED (named, not counted as passes): the three families whose argv takes a value only a CI run supplies (
check-cross-package-test-inputs --union-into ...,check-shard-attestation --emit ...,check-test-completeness ...), the 16 families derived against a changeset path that does not exist (none is owed —scripts/**publishes nothing), and the always-runs workflow tail.Whole-repo
pnpm lintwas narrowed, and the narrowing is proven, not assumed: (1) the file is in ESLint's own linted population —eslint --print-configresolves a config for it, exit 0; (2)--format jsonreports exactly 1 file linted, 0 errors, 0 warnings; (3) this repo runs oneeslint.config.mjswhich never enables type-aware linting for ANY file (noparserOptions.project—--print-configreturnsnullfor it; stated and independently measured ateslint.config.mjsaround line 327), so a one-file diff cannot move the verdict on any untouched file.Ablations
Both mutate a COMMITTED tree, prove the mutation landed on disk by counting the anchor and the injected text, restore with
git checkout HEAD -- ABSOLUTE_PATHunder anEXIT INT TERMtrap using absolute paths, and prove the restore by blob hash and an emptygit diff HEAD.e59375d0f→e596bba29read NOT MEASURED (baseline run failed (exit 1)); the printed-line control reds; the placement-separation control redsisEntrypoint(import.meta.url)exception removedthe isEntrypoint(import.meta.url) argument was rewritten) and the walking fixture readsDEFEATEDinstead of HELD — the predicted whole-census false direction, caughtBoth restores verified:
hash=e59375d0f007e75cd430fd3d5a01dd3486ac33bcmatchingHEAD,git diff HEADempty.No changeset:
scripts/**publishes nothing from any package (skip-changeset).🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code