Skip to content

fix(gate): check:node-esm-load grades only artifacts this tree produced - #7861

Merged
os-sam merged 2 commits into
mainfrom
claude/issue-7276-esm-load-foreign-artifacts
Sep 6, 2026
Merged

fix(gate): check:node-esm-load grades only artifacts this tree produced#7861
os-sam merged 2 commits into
mainfrom
claude/issue-7276-esm-load-foreign-artifacts

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Fixes #7276

End state taken: the banner becomes TRUE

Ruling 1 offered two acceptable end states. This PR takes the first one — the load leg really does refuse to grade artifacts it did not produce — and the sentence is rewritten only so it states the mechanism instead of an unbacked promise. Nothing is caveated away.

What was actually happening (re-derived, not transcribed)

turbo 2.10.9 does not merely store its cache outside the worktree. It announces on every run:

• Remote caching disabled, using shared worktree cache

Measured: a build in /home/user/objectui-issue-7276 wrote /home/user/objectui/.turbo/cache/c19befca204c7918.tar.zst — the MAIN checkout's cache dir, not the worktree's. So all worktrees of one clone share one cache by design, and the card's premise holds in a stronger form than it was filed with.

Reproduced on origin/main 52cac38, two worktrees of the same commit:

step reading
worktree A, cold turbo run build --filter=!@object-ui/site 43 tasks, 3m46.7s
worktree B, same command 43 of 43 cache hits, 272ms, FULL TURBO
worktree B, every restored .turbo/turbo-build.log names /home/user/objectui-issue-7276/...
worktree B, unpatched pnpm check:node-esm-load exit 0 — GREEN, Load leg: 34 of 39 ... imported and evaluated

That last row is the silent direction ruling 3 named, demonstrated: a green verdict over artifacts of which this tree produced exactly zero, under a banner promising the opposite. (Worktree B needed one nudge to reach it — apps/console/plugin.js had to be present, because it is missing from a cache replay for an unrelated reason now filed as #7855.)

The fix

A provenance leg between the build and the grading, reading a marker turbo already writes and already caches: each task's log, whose first line is pnpm's > name@version script ABSOLUTE-PACKAGE-DIR banner — the directory as it was when the script actually ran. A replay restores it verbatim, so it keeps naming the producing tree while the artifacts themselves are byte-identical either way.

It fails closed. own is the only verdict the load leg grades on; foreign, no-build-log and unreadable-build-log are all refusals that name themselves and carry their own remedy. A provenance check that answered "sure" when it could not read its marker would be this card's subject matter one level up.

Same tree as the table above, patched:

Provenance leg: 0 of 37 gradable entries were built by this tree.

✗ 37 of 37 entries REFUSED — the load leg does not grade what this tree did not produce ...

  foreign (37):
    @object-ui/app-shell  ←  /home/user/objectui-issue-7276/packages/app-shell
    @object-ui/auth  ←  /home/user/objectui-issue-7276/packages/auth
    ... and 27 more
  → turbo shares one cache across every worktree of a checkout ... Re-run with --force-build ...

Load leg: 0 of 39 published ESM entries imported and evaluated.
  refused on provenance, NOT graded: 37 (named by the provenance leg above)
✗ only 0 entries evaluated (expected at least 3). This run proved nothing ...

Exit 1, every foreign path named. On an honestly built tree it is Provenance leg: 37 of 37 gradable entries were built by this tree. and the load-leg verdict is unchanged from before this PR (34 of 39, exit 0).

Why detect rather than isolate — the cost reading (ruling 2)

wall clock
cold turbo run build --filter=!@object-ui/site, 43 tasks 3m46.7s
the same, all 43 replayed from the shared cache 213ms
ratio about 1065x
--force-build (TURBO_FORCE), whole gate end to end 257s, of which the build 3m17.9s

Making "I produced these" true by construction means paying the cold build on every run in any container where a sibling keeps the cache warm — which is every container this gate is run on. Both readings are shared-box wall clock under the container's verify lock, so treat the ratio as the durable number.

So: the refusal (which is what the banner actually promises) is always on and costs 37 small file reads. The isolated build is opt-in as --force-build, and the failure message points at it.

Both entry points (ruling 5)

check:esm-specifiers (--specifiers-only) reads sources and never touches an artifact, so it has no provenance question of its own — but it must not be read as having answered the load leg's. Its closing line now says what was not run:

--specifiers-only: the load leg (which builds, and grades only artifacts this tree
produced) was not run, so nothing above is a statement about built artifacts.

The file's header docblock — read by both doors — gains leg 3, and its Exit: contract gains the new failure.

The anti-vacuous leg (ruling 4), including one it failed

Four ablations, each mutated on disk with the hit count checked before and after, run, then restored to the HEAD blob hash:

ablation result
accept everything (code: PROVENANCE_OK) 1 test red
fail open on a missing log 1 test red
loosen the banner regex 2 tests red
move TURBO_TASK_LOG to another filename 52 green — the pin did not catch it

The fourth is the finding. Every fixture WRITES its log at TURBO_TASK_LOG, so they follow the constant wherever it goes and vouch for nothing — a sweep self-consistent with the thing it checks. The second commit pins the literal; re-ablated, it is red. The real-world signal for that failure is elsewhere and loud by construction: if turbo moves its task log, every package refuses at once as no-build-log, and the remedy text names the two identifiers to update.

The repository sweep is built from real manifests — every published package's real name, version and build script — and asserts both directions on each: the banner pnpm writes for it is recognised, and its own build-script line is not. A floor of MIN_PACKAGES keeps the sweep from becoming a loop over nothing.

Scope

Gates run locally (on b7a63bb)

gate verdict
pnpm check:node-esm-load exit 0 — Provenance leg: 37 of 37, Load leg: 34 of 39
pnpm check:esm-specifiers exit 0
pnpm test scripts/__tests__ (the CI job's command) exit 0 — 104 files, 3070 tests
pnpm type-check:scripts exit 0
pnpm lint:root (whole scan, not narrowed) exit 0 — 0 errors, 33 pre-existing warnings
node scripts/check-control-bytes.mjs exit 0 — 6365 files scanned
node scripts/check-changeset-presence.mjs exit 0 — none owed
node scripts/check-governed-queue-guard.mjs --test NOT GOVERNED

Generated by Claude Code

The load leg printed "the load leg refuses to grade artifacts it did not
produce" over a `pnpm build` that could not keep the promise. Measured on
turbo 2.10.9, which announces it every run as `using shared worktree cache`:
the cache is keyed by input hash and stored in the MAIN checkout's
`.turbo/cache`, so a build in one worktree is routinely satisfied by an entry
a sibling worktree wrote, and turbo restores that worktree's artifacts and its
log here.

Reproduced at 52cac38 in a second worktree of the same commit: 43 of 43 build
tasks replayed in 272ms, every task log naming the producing worktree, and the
gate then went GREEN over artifacts none of which this tree had produced.

Adds a provenance leg between the build and the grading. It reads the marker
turbo already writes and caches beside each task -- pnpm's
`> name@version script <absolute package dir>` banner, restored verbatim by a
replay, so it keeps naming the tree that produced the artifacts -- and refuses
to grade any package whose artifacts came from somewhere else, naming the path
they came from. It fails closed: `own` is the only verdict it grades on, so a
missing or unparseable marker is a refusal, never a pass.

Detection rather than isolation, on measurement: a cold
`turbo run build --filter=!@object-ui/site` took 3m46.7s over 43 tasks and the
same run against a warm shared cache took 213ms, about 1065x. `--force-build`
buys the isolated form (TURBO_FORCE) for callers who want it.

Both entry points stay honest: `--specifiers-only` now says the load leg
grades only artifacts this tree produced and that it was not run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDq78vMMSzCGWGmhUYBabh
…sweep

Measured: ablating TURBO_TASK_LOG to a different filename left all 52 tests in
this file green. Every fixture WRITES the log at TURBO_TASK_LOG, so they follow
the constant wherever it goes and vouch for nothing -- the anti-vacuous leg was
itself vacuous in that one direction.

Four ablations now, all red: accept-everything, fail-open on a missing log, a
moved marker path, and a loosened banner regex.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KDq78vMMSzCGWGmhUYBabh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants