diff --git a/scripts/ablation-dist-preflight.mjs b/scripts/ablation-dist-preflight.mjs index 17eed42b4e..ee1071562f 100644 --- a/scripts/ablation-dist-preflight.mjs +++ b/scripts/ablation-dist-preflight.mjs @@ -144,6 +144,7 @@ import { join, relative, resolve, extname } from 'node:path'; import { tmpdir } from 'node:os'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from './invoked-as.mjs'; const REPO_ROOT = resolve(fileURLToPath(import.meta.url), '..', '..'); @@ -394,5 +395,10 @@ function selfTest() { } const argv = process.argv.slice(2); -if (argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (argv.includes('--self-test')) selfTest(); else run(argv); diff --git a/scripts/check-dispatcher-error-vocabulary.mjs b/scripts/check-dispatcher-error-vocabulary.mjs index 747369e3b3..caa28de2dc 100644 --- a/scripts/check-dispatcher-error-vocabulary.mjs +++ b/scripts/check-dispatcher-error-vocabulary.mjs @@ -152,6 +152,7 @@ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs'; import { maskComments } from './js-comment-mask.mjs'; import { join, relative, dirname, resolve } from 'node:path'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = resolve(new URL('..', import.meta.url).pathname); const SCAN_ROOT = 'packages'; @@ -1826,4 +1827,7 @@ function main() { console.log(bounds); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-driver-memory-census.mjs b/scripts/check-driver-memory-census.mjs index 09a395f61d..22f1d37c1e 100644 --- a/scripts/check-driver-memory-census.mjs +++ b/scripts/check-driver-memory-census.mjs @@ -109,6 +109,7 @@ import { fileURLToPath } from 'node:url'; import { execFileSync } from 'node:child_process'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = join(dirname(fileURLToPath(import.meta.url)), '..'); const LEDGER_PATH = join(ROOT, 'scripts', 'driver-memory-census.ledger.json'); @@ -683,5 +684,10 @@ function selfTest() { } const argv = process.argv.slice(2); -if (argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (argv.includes('--self-test')) selfTest(); else report({ list: argv.includes('--list') }); diff --git a/scripts/check-engine-split-ratio.mjs b/scripts/check-engine-split-ratio.mjs index cc4c243e43..c41da1f50c 100644 --- a/scripts/check-engine-split-ratio.mjs +++ b/scripts/check-engine-split-ratio.mjs @@ -74,6 +74,7 @@ import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import { historyHorizon } from './pm/git-history.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const __dirname = dirname(fileURLToPath(import.meta.url)); @@ -334,4 +335,7 @@ function selfTest() { return failures === 0 ? 0 : 1; } -process.exit(process.argv.includes('--self-test') ? selfTest() : main(process.argv.slice(2))); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + process.exit(process.argv.includes('--self-test') ? selfTest() : main(process.argv.slice(2))); +} diff --git a/scripts/check-entry-guard.mjs b/scripts/check-entry-guard.mjs index 9275060393..11e18e3f39 100644 --- a/scripts/check-entry-guard.mjs +++ b/scripts/check-entry-guard.mjs @@ -435,39 +435,14 @@ export function importUnsafeStatements(source) { * names itself, which is what stops this from rotting into an allowlist. */ const KNOWN_IMPORT_UNSAFE = new Set([ - 'scripts/ablation-dist-preflight.mjs', 'scripts/check-changeset-no-major.mjs', - 'scripts/check-dispatcher-error-vocabulary.mjs', - 'scripts/check-driver-memory-census.mjs', 'scripts/check-empty-changeset.mjs', - 'scripts/check-engine-split-ratio.mjs', - 'scripts/check-error-code-casing.mjs', 'scripts/check-error-status-conformance.mjs', - 'scripts/check-examples-live-imports.mjs', - 'scripts/check-filter-alias-parity.mjs', - 'scripts/check-nul-bytes.mjs', - 'scripts/check-org-identifier.mjs', 'scripts/check-query-options-erasure-ratchet.mjs', - 'scripts/check-quick-reference-counts.mjs', - 'scripts/check-ratchet-remedy-authority.mjs', 'scripts/check-release-page-status.mjs', - 'scripts/check-required-contexts.mjs', - 'scripts/check-route-envelope.mjs', - 'scripts/check-runtime-services-index.mjs', - 'scripts/check-shard-attestation.mjs', - 'scripts/check-spec-parsed-alias.mjs', - 'scripts/check-startup-registry-verdict.mjs', - 'scripts/check-tenant-chokepoint.mjs', - 'scripts/check-test-completeness.mjs', - 'scripts/check-workflow-status-functions.mjs', 'scripts/checklist-select.mjs', - 'scripts/docs-audit/check-audit-scope.mjs', - 'scripts/measure-test-shard-timings.mjs', 'scripts/objectui-range.mjs', 'scripts/pm/check-governed-prose.mjs', - 'scripts/pm/check-label-desc-cap.mjs', - 'scripts/pm/check-skill-id-lint.mjs', - 'scripts/pm/check-skill-line-ratchet.mjs', 'scripts/qa/qa-rollup.mjs', 'scripts/ts-parse.mjs', ]); diff --git a/scripts/check-error-code-casing.mjs b/scripts/check-error-code-casing.mjs index 142e465d9c..2948a21c84 100644 --- a/scripts/check-error-code-casing.mjs +++ b/scripts/check-error-code-casing.mjs @@ -53,6 +53,7 @@ import { readFileSync, readdirSync, statSync } from 'node:fs'; import { maskComments } from './js-comment-mask.mjs'; import { join, relative, sep } from 'node:path'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = new URL('..', import.meta.url).pathname.replace(/\/$/, ''); const SCAN_ROOTS = ['packages']; @@ -241,4 +242,7 @@ If this literal is NOT an error.code — a field/param-addressed validator code process.exit(1); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-examples-live-imports.mjs b/scripts/check-examples-live-imports.mjs index 6c7a579642..71800f3a17 100644 --- a/scripts/check-examples-live-imports.mjs +++ b/scripts/check-examples-live-imports.mjs @@ -122,6 +122,7 @@ import { globToRegExp } from './check-cross-package-test-inputs.mjs'; import { join, resolve, relative, dirname, sep, posix } from 'node:path'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from './invoked-as.mjs'; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, '..'); @@ -759,7 +760,12 @@ function selfTest() { } const argv = process.argv.slice(2); -if (argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (argv.includes('--self-test')) selfTest(); else if (argv.includes('--list')) list(); else if (argv.includes('--json')) { const { rows, unresolved } = collect(); diff --git a/scripts/check-filter-alias-parity.mjs b/scripts/check-filter-alias-parity.mjs index d0747301c9..d92a734e81 100644 --- a/scripts/check-filter-alias-parity.mjs +++ b/scripts/check-filter-alias-parity.mjs @@ -88,6 +88,7 @@ import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); @@ -648,4 +649,7 @@ function main() { process.exit(1); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-nul-bytes.mjs b/scripts/check-nul-bytes.mjs index 00d0c58c3e..944267042b 100644 --- a/scripts/check-nul-bytes.mjs +++ b/scripts/check-nul-bytes.mjs @@ -269,6 +269,7 @@ import { lstatSync, mkdirSync, mkdtempSync, readFileSync, rmSync, symlinkSync, w import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { isEntrypoint } from './invoked-as.mjs'; /** * The scanned set as a 256-entry lookup: every ASCII control character except @@ -1155,7 +1156,12 @@ function selfTest() { console.log(`✓ check-nul-bytes --self-test: ${checked} assertions over a temp git repo (real scan() path)`); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { selfTest(); } else if (process.argv.includes('--list')) { const result = scan(repoRoot()); diff --git a/scripts/check-org-identifier.mjs b/scripts/check-org-identifier.mjs index 438702306b..f54c84619a 100644 --- a/scripts/check-org-identifier.mjs +++ b/scripts/check-org-identifier.mjs @@ -271,6 +271,7 @@ import { join } from 'node:path'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; import { maskComments } from './js-comment-mask.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOTS = ['examples', 'apps', 'packages']; const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs', '.cjs', '.cts', '.mts']; @@ -785,4 +786,7 @@ cheapest way to silence it while leaving the dead read in place.`); process.exit(1); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-quick-reference-counts.mjs b/scripts/check-quick-reference-counts.mjs index 6f7b632ead..e3ffc98a38 100644 --- a/scripts/check-quick-reference-counts.mjs +++ b/scripts/check-quick-reference-counts.mjs @@ -101,6 +101,7 @@ import { readFileSync, readdirSync, existsSync } from 'node:fs'; import { join } from 'node:path'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = new URL('..', import.meta.url).pathname.replace(/\/$/, ''); const TARGET = 'content/docs/getting-started/quick-reference.mdx'; @@ -855,4 +856,7 @@ quietly stops recognising its page reports success forever. process.exit(1); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-ratchet-remedy-authority.mjs b/scripts/check-ratchet-remedy-authority.mjs index 22deab58f2..e619d38bd7 100644 --- a/scripts/check-ratchet-remedy-authority.mjs +++ b/scripts/check-ratchet-remedy-authority.mjs @@ -107,6 +107,7 @@ import { readFileSync, readdirSync } from 'node:fs'; import { join, dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from './invoked-as.mjs'; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = resolve(HERE, '..'); @@ -982,6 +983,11 @@ function selfTest() { process.exit(0); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else if (process.argv.includes('--list')) list(); else main(); diff --git a/scripts/check-required-contexts.mjs b/scripts/check-required-contexts.mjs index 387ede433a..222404ead5 100644 --- a/scripts/check-required-contexts.mjs +++ b/scripts/check-required-contexts.mjs @@ -181,6 +181,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { isEntrypoint } from './invoked-as.mjs'; /** * The branch-protection-required check contexts, as this repository declares @@ -2266,7 +2267,12 @@ async function selfTest() { ); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { await selfTest(); } else if (process.argv.includes('--verify-required-set')) { // Report-only, off the required path (#9642). Exit 0 = swept (0 or N diff --git a/scripts/check-route-envelope.mjs b/scripts/check-route-envelope.mjs index a4c76d7a6a..a0f936cec2 100644 --- a/scripts/check-route-envelope.mjs +++ b/scripts/check-route-envelope.mjs @@ -144,6 +144,7 @@ import { join, relative, sep } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); @@ -2582,5 +2583,10 @@ function selfTest() { console.log('✓ check-route-envelope self-test passed'); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else audit(); diff --git a/scripts/check-runtime-services-index.mjs b/scripts/check-runtime-services-index.mjs index 00e6f2d46e..3c0118964b 100644 --- a/scripts/check-runtime-services-index.mjs +++ b/scripts/check-runtime-services-index.mjs @@ -229,6 +229,7 @@ import { readFileSync, readdirSync, statSync, existsSync, mkdtempSync, mkdirSync import { join, dirname, relative, sep } from 'node:path'; import { tmpdir } from 'node:os'; import { fileURLToPath } from 'node:url'; +import { isEntrypoint } from './invoked-as.mjs'; const HERE = dirname(fileURLToPath(import.meta.url)); const repoRoot = () => join(HERE, '..'); @@ -1064,5 +1065,10 @@ function selfTest() { console.log(`✓ check-runtime-services-index --self-test: ${checked} assertions over a temp fixture (real run() path); every limb -- chapter list, kernel table, meta.json, order, href, title premise, registry slot (incl. the split-line registration), stability matrix (missing row, stale row, order) and stability LABEL on both tables, canonical-source rows (page-less row, page with no row, prose label, duplicate, missing path, and never read as a stability claim), label VOCABULARY (undefined label named with its allowed set and reported only against the page, every defined label accepted, the two legends drifting apart from EACH OTHER while every label they name is still in the enum, a legend widening it alone, legend order, section scoping past a decoy in each file, and a missing legend refused), empty tree, missing versioning.mdx, empty Source-of-Truth list -- observed FAILING and observed silent.`); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else main(); diff --git a/scripts/check-shard-attestation.mjs b/scripts/check-shard-attestation.mjs index 0d47264143..ebe8e2ae48 100644 --- a/scripts/check-shard-attestation.mjs +++ b/scripts/check-shard-attestation.mjs @@ -122,6 +122,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, import { tmpdir } from 'node:os'; import { dirname, join, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; +import { isEntrypoint } from './invoked-as.mjs'; /** Artifact-name prefix shared by every shard credential. */ const ARTIFACT_PREFIX = 'shard-attest-'; @@ -948,7 +949,12 @@ async function selfTest() { ); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { await selfTest(); } else if (process.argv.includes('--emit')) { emit(); diff --git a/scripts/check-spec-parsed-alias.mjs b/scripts/check-spec-parsed-alias.mjs index ade025dfee..aa9895fa3a 100644 --- a/scripts/check-spec-parsed-alias.mjs +++ b/scripts/check-spec-parsed-alias.mjs @@ -94,6 +94,7 @@ import { readFileSync, readdirSync, statSync } from 'node:fs'; import { join, relative } from 'node:path'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = new URL('..', import.meta.url).pathname.replace(/\/$/, ''); const SPEC_SRC = join(ROOT, 'packages/spec/src'); @@ -461,7 +462,12 @@ export type Iso0 = Assert, z.infer< typeof console.log('check-spec-parsed-alias --self-test: 18 assertions passed'); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { selfTest(); } else { const pins = readIsomorphicPins(readFileSync(PIN_FILE, 'utf8')); diff --git a/scripts/check-startup-registry-verdict.mjs b/scripts/check-startup-registry-verdict.mjs index 90920ccab5..d5e4f98f11 100644 --- a/scripts/check-startup-registry-verdict.mjs +++ b/scripts/check-startup-registry-verdict.mjs @@ -150,6 +150,7 @@ import { join, relative, sep, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = fileURLToPath(new URL('..', import.meta.url)); const BASELINE_PATH = join(ROOT, 'scripts', 'startup-registry-verdict.baseline.json'); @@ -1436,7 +1437,12 @@ function selfTest() { } const args = process.argv.slice(2); -if (args.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (args.includes('--self-test')) { process.exit(selfTest()); } else { const dirFlag = args.indexOf('--packages-dir'); diff --git a/scripts/check-tenant-chokepoint.mjs b/scripts/check-tenant-chokepoint.mjs index 9ca7c69bd9..e1f5b1e6e0 100644 --- a/scripts/check-tenant-chokepoint.mjs +++ b/scripts/check-tenant-chokepoint.mjs @@ -112,6 +112,7 @@ import { join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; import ts from 'typescript'; import { parseSourceFile } from './ts-parse.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const ROOT = join(fileURLToPath(new URL('.', import.meta.url)), '..'); @@ -554,9 +555,14 @@ above catches it" is not one: this asserts the chokepoint's own contract.`); ); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { selfTest(); process.exit(0); } -main(); +if (invokedDirectly) main(); diff --git a/scripts/check-test-completeness.mjs b/scripts/check-test-completeness.mjs index 082f4523b1..707e5ad676 100644 --- a/scripts/check-test-completeness.mjs +++ b/scripts/check-test-completeness.mjs @@ -105,6 +105,7 @@ import { readFileSync, readdirSync } from 'node:fs'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from './invoked-as.mjs'; const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); @@ -905,4 +906,7 @@ silently did not run.`); process.exit(1); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/check-workflow-status-functions.mjs b/scripts/check-workflow-status-functions.mjs index 51ed8b373c..bfc8900682 100644 --- a/scripts/check-workflow-status-functions.mjs +++ b/scripts/check-workflow-status-functions.mjs @@ -76,6 +76,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync, import { tmpdir } from 'node:os'; import { dirname, join } from 'node:path'; import { LineCounter, isMap, isScalar, parseDocument } from 'yaml'; +import { isEntrypoint } from './invoked-as.mjs'; const WORKFLOW_DIR = '.github/workflows'; @@ -600,7 +601,12 @@ jobs: console.log(`✓ check-workflow-status-functions --self-test: ${checked} assertions over temp fixture roots (real scan() path)`); } -if (process.argv.includes('--self-test')) { +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) { selfTest(); } else if (process.argv.includes('--list')) { list(); diff --git a/scripts/docs-audit/check-audit-scope.mjs b/scripts/docs-audit/check-audit-scope.mjs index 80d95eb743..d784b2dd6b 100644 --- a/scripts/docs-audit/check-audit-scope.mjs +++ b/scripts/docs-audit/check-audit-scope.mjs @@ -87,6 +87,7 @@ import { readFileSync, writeFileSync } from 'node:fs'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; import { createContext, runInContext } from 'node:vm'; +import { isEntrypoint } from '../invoked-as.mjs'; const HERE = dirname(fileURLToPath(import.meta.url)); const REPO_ROOT = execFileSync('git', ['rev-parse', '--show-toplevel'], { cwd: HERE }) @@ -466,17 +467,20 @@ export async function checkReadOnlyRouting(source) { // --- main -------------------------------------------------------------------- -try { - if (args.includes('--self-test')) { - await selfTest(); - process.exit(0); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + try { + if (args.includes('--self-test')) { + await selfTest(); + process.exit(0); + } + await main(); + } catch (e) { + // A structural failure (markers gone, list unparseable, derivation empty) is + // a RED result with a readable reason — never a stack trace, never a pass. + console.error(`✗ ${e.message}`); + process.exit(1); } - await main(); -} catch (e) { - // A structural failure (markers gone, list unparseable, derivation empty) is a - // RED result with a readable reason — never a stack trace, and never a pass. - console.error(`✗ ${e.message}`); - process.exit(1); } async function main() { diff --git a/scripts/measure-test-shard-timings.mjs b/scripts/measure-test-shard-timings.mjs index b909ec4d1c..924c32ed46 100644 --- a/scripts/measure-test-shard-timings.mjs +++ b/scripts/measure-test-shard-timings.mjs @@ -58,6 +58,7 @@ import { fileURLToPath } from 'node:url'; import process from 'node:process'; import { countTestFiles } from './partition-test-shards.mjs'; +import { isEntrypoint } from './invoked-as.mjs'; const REPO_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const DEFAULT_OUT = path.join(REPO_ROOT, 'scripts', 'test-shard-timings.json'); @@ -382,4 +383,7 @@ function main() { ); } -main(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +if (isEntrypoint(import.meta.url)) { + main(); +} diff --git a/scripts/pm/check-label-desc-cap.mjs b/scripts/pm/check-label-desc-cap.mjs index b83d6b158c..bb1cb8e7b3 100644 --- a/scripts/pm/check-label-desc-cap.mjs +++ b/scripts/pm/check-label-desc-cap.mjs @@ -83,6 +83,7 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from '../invoked-as.mjs'; const REPO_ROOT = join(fileURLToPath(import.meta.url), '..', '..', '..'); @@ -477,5 +478,10 @@ function selfTest() { console.log('\n✓ check-label-desc-cap --self-test: all cases passed'); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else run(); diff --git a/scripts/pm/check-skill-id-lint.mjs b/scripts/pm/check-skill-id-lint.mjs index 1044b5356a..a00c6354f6 100644 --- a/scripts/pm/check-skill-id-lint.mjs +++ b/scripts/pm/check-skill-id-lint.mjs @@ -47,6 +47,7 @@ import { readFileSync, readdirSync, statSync } from 'node:fs'; import { join, relative } from 'node:path'; import { fileURLToPath } from 'node:url'; import process from 'node:process'; +import { isEntrypoint } from '../invoked-as.mjs'; const REPO_ROOT = join(fileURLToPath(import.meta.url), '..', '..', '..'); @@ -203,5 +204,10 @@ function selfTest() { console.log(`✓ check-skill-id-lint self-test: ${cases.length} cases pass.`); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else run(); diff --git a/scripts/pm/check-skill-line-ratchet.mjs b/scripts/pm/check-skill-line-ratchet.mjs index 909cf4cf82..ac29e415e7 100644 --- a/scripts/pm/check-skill-line-ratchet.mjs +++ b/scripts/pm/check-skill-line-ratchet.mjs @@ -76,6 +76,7 @@ import { readFileSync } from 'node:fs'; import process from 'node:process'; +import { isEntrypoint } from '../invoked-as.mjs'; const REPO_ROOT = new URL('../../', import.meta.url); @@ -272,5 +273,10 @@ function selfTest() { console.log(`✓ check-skill-line-ratchet self-test: ${cases.length} cases pass.`); } -if (process.argv.includes('--self-test')) selfTest(); +// Exports bindings, so an import for those exports alone must run nothing (#10667). +const invokedDirectly = isEntrypoint(import.meta.url); + +if (!invokedDirectly) { + // imported as a module — expose the exports and do nothing else +} else if (process.argv.includes('--self-test')) selfTest(); else run();