diff --git a/package.json b/package.json index 157c0b860bf..ea2b866912b 100644 --- a/package.json +++ b/package.json @@ -1657,7 +1657,7 @@ "@types/markdown-it": "^14.1.2", "@types/node": "25.6.0", "@types/ws": "^8.18.1", - "@typescript/native-preview": "7.0.0-dev.20260423.1", + "@typescript/native-preview": "7.0.0-dev.20260421.2", "@vitest/coverage-v8": "^4.1.5", "jscpd": "4.0.9", "jsdom": "^29.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a7f6ab0d2b2..ad00dd55e03 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -176,8 +176,8 @@ importers: specifier: ^8.18.1 version: 8.18.1 '@typescript/native-preview': - specifier: 7.0.0-dev.20260423.1 - version: 7.0.0-dev.20260423.1 + specifier: 7.0.0-dev.20260421.2 + version: 7.0.0-dev.20260421.2 '@vitest/coverage-v8': specifier: ^4.1.5 version: 4.1.5(@vitest/browser@4.1.5)(vitest@4.1.5) @@ -204,7 +204,7 @@ importers: version: 0.21.1(signal-polyfill@0.2.2) tsdown: specifier: 0.21.9 - version: 0.21.9(@typescript/native-preview@7.0.0-dev.20260423.1)(typescript@6.0.3) + version: 0.21.9(@typescript/native-preview@7.0.0-dev.20260421.2)(typescript@6.0.3) tsx: specifier: ^4.21.0 version: 4.21.0 @@ -4081,51 +4081,43 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-wbLr6o5fROaCYt6cOpFhbe92FJAOdhAHwm/s8I/IyN5HbL1ULgel/wHaZiR+ws+27rgruNUiCENzTUg9vSz2bA==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-fHv1r3ZmVo6zxuAIFmuX3w9QxbcauoG0SsWhmDwm6VmRubLlOJIcmTtlmV3JAb9oOnq8LuzZljzT7Q39fSMQDw==} cpu: [arm64] os: [darwin] - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-13MpNT+4MgkgrfiW2u03rnER5aB3yz9fA0bWEYh6IH3rIqA2AR3Dntp3QXW4sQrZf0SriXqHe2R7X3HCT5xmqA==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-KWTR6xbW9t+JS7D5DQIzo75pqVXVWUxF9PMv/+S6xsnOjCVd6g0ixHcFpFMJMKSUQpGPr8Z5f7b8ks6LHW01jg==} cpu: [x64] os: [darwin] - '@typescript/native-preview-linux-arm64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-ICIkJDTqmn0R4Vs811+Ht2RYTk1OCrAhHCu0JthmhR216T1Tqgi5DWRoCprp3RL1qU6fLnxxrIpEbNlNN7XFYA==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-VLMEuml3BhUb+jaL0TXQ4xvVODxJF+RhkI+tBWvlynsJI4khTXEiwWh+wPOJrsfBRYFRMXEu28Odl/HXkYze8w==} cpu: [arm64] os: [linux] - '@typescript/native-preview-linux-arm@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-CxUA15qbPQRvz2nanBpiv1h4tgXTCJJwqOtgKMSdIuPkow8dyYW3ba5oLoH/jZhS4792XislX659hlFrfiU6CQ==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-BWLQO3nemLDSV5PoE5GPHe1dU9Dth77Kv8/cle9Ujcp4LhPo0KincdPqFH/qKeU/xvW25mgFueflZ1nc4rKuww==} cpu: [arm] os: [linux] - '@typescript/native-preview-linux-x64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-cWLFS4R8dOU1YuUJ/2VLeGMVIjgI3GGb/f9rRY5MbWHq5l3NNZh8y1QwAOrTh3+g3q6+znArfxVnD2hZHUz8Mw==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-qUrJWTB5/wv4wnRG0TRXElAxc2kykNiRNyEIEqBbLmzDlrcvAW7RRy8MXoY1ZyTiKGMu14itZ3x9oW6+blFpRw==} cpu: [x64] os: [linux] - '@typescript/native-preview-win32-arm64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-OWaGUI4+dHqYZv+k6sITx9Y27FNy3XzNFk4OrOiYtBkIO/xrb9TPMP4A5XI4n5zwRLIv3xne9g039xgRbaeyoQ==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-Rc6NsWlZmCs5YUKVzKgwoBOoRUGsPzct4BDMRX0csD1devLBBc4AbUXWKsJRbpwIAnqMO1ld4sNHEb+wXgfNHQ==} cpu: [arm64] os: [win32] - '@typescript/native-preview-win32-x64@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-5MQjO/qdLwXpjW7Dy/1lNv7Vtpvo6bhCkbjan4PoRN5/eeyqEqDWxdf8AGE4btLmHqyIjEHRuYf7kp2tlAr6lQ==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-GQv1+dya1t6EqF2Cpsb+xoozovdX10JUSf6Kl/8xNkTapzmlHd+uMr+8ku3jIASTxoRGn0Mklgjj3MDKrOTuLg==} cpu: [x64] os: [win32] - '@typescript/native-preview@7.0.0-dev.20260423.1': - resolution: {integrity: sha512-9WD7TJJlGvt9PQqJI/+44dVP4oqGQFIkYrpXt7nlQ0WgNIErN52x/XhxmJ4nWft06qejgPiUbPo4aYRNOmIHXg==} - engines: {node: '>=16.20.0'} + '@typescript/native-preview@7.0.0-dev.20260421.2': + resolution: {integrity: sha512-CmajHI25HpVWE9R1XFoxr+cphJPxoYD3eFioQtAvXYkMFKnLdICMS9pXre9Pybizb75ejRxjKD5/CVG055rEIg==} hasBin: true '@typespec/ts-http-runtime@0.3.5': @@ -10777,36 +10769,36 @@ snapshots: '@types/node': 25.6.0 optional: true - '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260423.1': + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-darwin-x64@7.0.0-dev.20260423.1': + '@typescript/native-preview-darwin-x64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-linux-arm64@7.0.0-dev.20260423.1': + '@typescript/native-preview-linux-arm64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-linux-arm@7.0.0-dev.20260423.1': + '@typescript/native-preview-linux-arm@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-linux-x64@7.0.0-dev.20260423.1': + '@typescript/native-preview-linux-x64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-win32-arm64@7.0.0-dev.20260423.1': + '@typescript/native-preview-win32-arm64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview-win32-x64@7.0.0-dev.20260423.1': + '@typescript/native-preview-win32-x64@7.0.0-dev.20260421.2': optional: true - '@typescript/native-preview@7.0.0-dev.20260423.1': + '@typescript/native-preview@7.0.0-dev.20260421.2': optionalDependencies: - '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260423.1 - '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260423.1 - '@typescript/native-preview-linux-arm': 7.0.0-dev.20260423.1 - '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260423.1 - '@typescript/native-preview-linux-x64': 7.0.0-dev.20260423.1 - '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260423.1 - '@typescript/native-preview-win32-x64': 7.0.0-dev.20260423.1 + '@typescript/native-preview-darwin-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-darwin-x64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-arm': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-linux-x64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-win32-arm64': 7.0.0-dev.20260421.2 + '@typescript/native-preview-win32-x64': 7.0.0-dev.20260421.2 '@typespec/ts-http-runtime@0.3.5': dependencies: @@ -13850,7 +13842,7 @@ snapshots: glob: 7.2.3 optional: true - rolldown-plugin-dts@0.23.2(@typescript/native-preview@7.0.0-dev.20260423.1)(rolldown@1.0.0-rc.16)(typescript@6.0.3): + rolldown-plugin-dts@0.23.2(@typescript/native-preview@7.0.0-dev.20260421.2)(rolldown@1.0.0-rc.16)(typescript@6.0.3): dependencies: '@babel/generator': 8.0.0-rc.3 '@babel/helper-validator-identifier': 8.0.0-rc.3 @@ -13864,7 +13856,7 @@ snapshots: picomatch: 4.0.4 rolldown: 1.0.0-rc.16 optionalDependencies: - '@typescript/native-preview': 7.0.0-dev.20260423.1 + '@typescript/native-preview': 7.0.0-dev.20260421.2 typescript: 6.0.3 transitivePeerDependencies: - oxc-resolver @@ -14349,7 +14341,7 @@ snapshots: ts-algebra@2.0.0: {} - tsdown@0.21.9(@typescript/native-preview@7.0.0-dev.20260423.1)(typescript@6.0.3): + tsdown@0.21.9(@typescript/native-preview@7.0.0-dev.20260421.2)(typescript@6.0.3): dependencies: ansis: 4.2.0 cac: 7.0.0 @@ -14360,7 +14352,7 @@ snapshots: obug: 2.1.1 picomatch: 4.0.4 rolldown: 1.0.0-rc.16 - rolldown-plugin-dts: 0.23.2(@typescript/native-preview@7.0.0-dev.20260423.1)(rolldown@1.0.0-rc.16)(typescript@6.0.3) + rolldown-plugin-dts: 0.23.2(@typescript/native-preview@7.0.0-dev.20260421.2)(rolldown@1.0.0-rc.16)(typescript@6.0.3) semver: 7.7.4 tinyexec: 1.1.1 tinyglobby: 0.2.16 diff --git a/scripts/lib/vitest-local-scheduling.d.mts b/scripts/lib/vitest-local-scheduling.d.mts index bca6e722319..ecf8a3348ff 100644 --- a/scripts/lib/vitest-local-scheduling.d.mts +++ b/scripts/lib/vitest-local-scheduling.d.mts @@ -16,6 +16,9 @@ export const DEFAULT_LOCAL_FULL_SUITE_VITEST_WORKERS: number; export const LARGE_LOCAL_FULL_SUITE_VITEST_WORKERS: number; export function isCiLikeEnv(env?: Record): boolean; +export function resolveLocalVitestEnv( + env?: Record, +): Record; export function detectVitestHostInfo(): Required; export function resolveLocalVitestMaxWorkers( env?: Record, diff --git a/scripts/lib/vitest-local-scheduling.mjs b/scripts/lib/vitest-local-scheduling.mjs index 4ef453839a8..f94707100f1 100644 --- a/scripts/lib/vitest-local-scheduling.mjs +++ b/scripts/lib/vitest-local-scheduling.mjs @@ -24,6 +24,18 @@ export function isCiLikeEnv(env = process.env) { return env.CI === "true" || env.GITHUB_ACTIONS === "true"; } +export function resolveLocalVitestEnv(env = process.env) { + const normalizedLocalCheck = env.OPENCLAW_LOCAL_CHECK?.trim().toLowerCase(); + if (isCiLikeEnv(env) || (normalizedLocalCheck !== "0" && normalizedLocalCheck !== "false")) { + return env; + } + + return { + ...env, + OPENCLAW_LOCAL_CHECK: "1", + }; +} + export function detectVitestHostInfo() { return { cpuCount: diff --git a/scripts/run-vitest.mjs b/scripts/run-vitest.mjs index 6dc435f8895..f4a0ce8e384 100644 --- a/scripts/run-vitest.mjs +++ b/scripts/run-vitest.mjs @@ -1,6 +1,7 @@ import { spawn } from "node:child_process"; import { createRequire } from "node:module"; import path from "node:path"; +import { resolveLocalVitestEnv } from "./lib/vitest-local-scheduling.mjs"; import { spawnPnpmRunner } from "./pnpm-runner.mjs"; import { forwardSignalToVitestProcessGroup, @@ -47,15 +48,16 @@ export function resolveVitestSpawnParams(env = process.env, platform = process.p } export function resolveVitestSpawnEnv(env = process.env) { - if (!shouldApplyNativeWorkerBudget(env)) { - return env; + const nextEnv = resolveLocalVitestEnv(env); + if (!shouldApplyNativeWorkerBudget(nextEnv)) { + return nextEnv; } - const nativeWorkerCount = String(resolveNativeWorkerCount(env)); + const nativeWorkerCount = String(resolveNativeWorkerCount(nextEnv)); return { - ...env, - RAYON_NUM_THREADS: env.RAYON_NUM_THREADS?.trim() || nativeWorkerCount, - TOKIO_WORKER_THREADS: env.TOKIO_WORKER_THREADS?.trim() || nativeWorkerCount, + ...nextEnv, + RAYON_NUM_THREADS: nextEnv.RAYON_NUM_THREADS?.trim() || nativeWorkerCount, + TOKIO_WORKER_THREADS: nextEnv.TOKIO_WORKER_THREADS?.trim() || nativeWorkerCount, }; } diff --git a/scripts/test-projects.mjs b/scripts/test-projects.mjs index bfa58a763a7..83669bdd8f5 100644 --- a/scripts/test-projects.mjs +++ b/scripts/test-projects.mjs @@ -2,7 +2,11 @@ import fs from "node:fs"; import path from "node:path"; import { performance } from "node:perf_hooks"; import { acquireLocalHeavyCheckLockSync } from "./lib/local-heavy-check-runtime.mjs"; -import { isCiLikeEnv, resolveLocalFullSuiteProfile } from "./lib/vitest-local-scheduling.mjs"; +import { + isCiLikeEnv, + resolveLocalFullSuiteProfile, + resolveLocalVitestEnv, +} from "./lib/vitest-local-scheduling.mjs"; import { resolveVitestCliEntry, resolveVitestNodeArgs, @@ -341,6 +345,7 @@ async function runVitestSpecsParallel(specs, concurrency) { async function main() { const args = process.argv.slice(2); + const baseEnv = resolveLocalVitestEnv(process.env); const { targetArgs } = parseTestProjectsArgs(args, process.cwd()); const changedTargetArgs = targetArgs.length === 0 ? resolveChangedTargetArgs(args, process.cwd()) : null; @@ -349,7 +354,7 @@ async function main() { ? buildFullSuiteVitestRunPlans(args, process.cwd()).map((plan) => ({ config: plan.config, continueOnFailure: true, - env: process.env, + env: baseEnv, includeFilePath: null, includePatterns: null, pnpmArgs: [ @@ -365,12 +370,12 @@ async function main() { watchMode: plan.watchMode, })) : createVitestRunSpecs(args, { - baseEnv: process.env, + baseEnv, cwd: process.cwd(), }); const runSpecs = applyDefaultMultiSpecVitestCachePaths( - applyDefaultVitestNoOutputTimeout(rawRunSpecs, { env: process.env }), - { cwd: process.cwd(), env: process.env }, + applyDefaultVitestNoOutputTimeout(rawRunSpecs, { env: baseEnv }), + { cwd: process.cwd(), env: baseEnv }, ); if (runSpecs.length === 0) { @@ -378,10 +383,10 @@ async function main() { return; } - releaseLock = shouldAcquireLocalHeavyCheckLock(runSpecs, process.env) + releaseLock = shouldAcquireLocalHeavyCheckLock(runSpecs, baseEnv) ? acquireLocalHeavyCheckLockSync({ cwd: process.cwd(), - env: process.env, + env: baseEnv, toolName: "test", }) : () => {}; @@ -391,28 +396,28 @@ async function main() { changedTargetArgs === null && !runSpecs.some((spec) => spec.watchMode); const isExplicitParallelMultiConfigRun = - Boolean(process.env.OPENCLAW_TEST_PROJECTS_PARALLEL) && + Boolean(baseEnv.OPENCLAW_TEST_PROJECTS_PARALLEL) && runSpecs.length > 1 && !runSpecs.some((spec) => spec.watchMode); const isParallelShardRun = isFullSuiteRun || isFullExtensionsProjectRun(runSpecs) || isExplicitParallelMultiConfigRun; if (isParallelShardRun) { - const concurrency = resolveParallelFullSuiteConcurrency(runSpecs.length, process.env); + const concurrency = resolveParallelFullSuiteConcurrency(runSpecs.length, baseEnv); if (concurrency > 1) { - const localFullSuiteProfile = resolveLocalFullSuiteProfile(process.env); - const shardTimings = readShardTimings(process.cwd(), process.env); + const localFullSuiteProfile = resolveLocalFullSuiteProfile(baseEnv); + const shardTimings = readShardTimings(process.cwd(), baseEnv); const parallelSpecs = applyDefaultParallelVitestWorkerBudget( applyParallelVitestCachePaths(orderFullSuiteSpecsForParallelRun(runSpecs, shardTimings), { cwd: process.cwd(), - env: process.env, + env: baseEnv, }), - process.env, + baseEnv, ); if ( - !isCiLikeEnv(process.env) && - !process.env.OPENCLAW_TEST_PROJECTS_PARALLEL && - !process.env.OPENCLAW_VITEST_MAX_WORKERS && - !process.env.OPENCLAW_TEST_WORKERS && + !isCiLikeEnv(baseEnv) && + !baseEnv.OPENCLAW_TEST_PROJECTS_PARALLEL && + !baseEnv.OPENCLAW_VITEST_MAX_WORKERS && + !baseEnv.OPENCLAW_TEST_WORKERS && localFullSuiteProfile.shardParallelism === 10 && localFullSuiteProfile.vitestMaxWorkers === 2 ) { @@ -425,7 +430,7 @@ async function main() { parallelSpecs, concurrency, ); - writeShardTimings(timings, process.cwd(), process.env); + writeShardTimings(timings, process.cwd(), baseEnv); console.error( `[test] completed ${parallelSpecs.length} Vitest shards; Vitest summaries above are per-shard, not aggregate totals.`, ); @@ -455,7 +460,7 @@ async function main() { timings.push(result.timing); } } - writeShardTimings(timings, process.cwd(), process.env); + writeShardTimings(timings, process.cwd(), baseEnv); releaseLockOnce(); if (exitCode !== 0) { diff --git a/test/scripts/run-vitest.test.ts b/test/scripts/run-vitest.test.ts index 1088ffcc05d..69acaffb27d 100644 --- a/test/scripts/run-vitest.test.ts +++ b/test/scripts/run-vitest.test.ts @@ -58,6 +58,38 @@ describe("scripts/run-vitest", () => { }); }); + it("reenables local check policy for local Vitest children", () => { + expect( + resolveVitestSpawnParams( + { + OPENCLAW_LOCAL_CHECK: "0", + PATH: "/usr/bin", + }, + "darwin", + ).env, + ).toMatchObject({ + OPENCLAW_LOCAL_CHECK: "1", + PATH: "/usr/bin", + }); + }); + + it("preserves explicit local-check disablement in CI", () => { + expect( + resolveVitestSpawnParams( + { + CI: "true", + OPENCLAW_LOCAL_CHECK: "0", + PATH: "/usr/bin", + }, + "linux", + ).env, + ).toMatchObject({ + CI: "true", + OPENCLAW_LOCAL_CHECK: "0", + PATH: "/usr/bin", + }); + }); + it("caps native Rust worker pools for serial Vitest runs", () => { expect( resolveVitestSpawnParams( diff --git a/test/scripts/vitest-local-scheduling.test.ts b/test/scripts/vitest-local-scheduling.test.ts index 3dacf7ea7be..d8dcd72f6f1 100644 --- a/test/scripts/vitest-local-scheduling.test.ts +++ b/test/scripts/vitest-local-scheduling.test.ts @@ -1,11 +1,37 @@ import { describe, expect, it } from "vitest"; import { + resolveLocalVitestEnv, resolveLocalFullSuiteProfile, resolveLocalVitestScheduling, shouldUseLargeLocalFullSuiteProfile, } from "../../scripts/lib/vitest-local-scheduling.mjs"; describe("vitest local full-suite profile", () => { + it("forces local Vitest runs back onto local-check policy", () => { + expect(resolveLocalVitestEnv({ OPENCLAW_LOCAL_CHECK: "0", PATH: "/usr/bin" })).toEqual({ + OPENCLAW_LOCAL_CHECK: "1", + PATH: "/usr/bin", + }); + expect(resolveLocalVitestEnv({ OPENCLAW_LOCAL_CHECK: "false", PATH: "/usr/bin" })).toEqual({ + OPENCLAW_LOCAL_CHECK: "1", + PATH: "/usr/bin", + }); + }); + + it("keeps local-check disablement for CI Vitest runs", () => { + expect( + resolveLocalVitestEnv({ + CI: "true", + OPENCLAW_LOCAL_CHECK: "0", + PATH: "/usr/bin", + }), + ).toEqual({ + CI: "true", + OPENCLAW_LOCAL_CHECK: "0", + PATH: "/usr/bin", + }); + }); + it("selects the large local profile on roomy hosts that are not throttled", () => { const env = {}; const hostInfo = {