fix(tooling): avoid build and test startup stalls on shared tsx caches (#130924)

* fix(tooling): avoid shared tsx cache startup stalls

Use the shared preloader before tsx initializes so maintained build, check, and test commands retain memory transforms without scanning other checkouts' disk caches. Preserve changed-cwd forks and copied tooling closures.

* test: align command contracts with tooling bootstrap
This commit is contained in:
Peter Steinberger
2026-08-27 10:36:12 -07:00
committed by GitHub
parent fdefa6733d
commit ce0fafefce
21 changed files with 703 additions and 359 deletions
+1
View File
@@ -22,6 +22,7 @@ on:
- "scripts/lib/plugin-npm-package-manifest.mts"
- "scripts/lib/tsx-cli-shim.mjs"
- "scripts/lib/local-check-runtime.mts"
- "scripts/tsx.mjs"
- "scripts/lib/plugin-npm-release.ts"
- "scripts/lib/plugin-publication-candidates.ts"
- "scripts/lib/plugin-publication-collector.ts"
+6
View File
@@ -79,6 +79,12 @@ reconcile dependencies before the remote wrapper starts.
## Core commands
Maintained JavaScript tooling wrappers and root package commands use tsx's
in-process transform cache. They skip its shared disk cache before the loader
starts, and child tooling inherits that policy. This does not relocate or clean
temporary directories, Node or Vitest caches, or other global caches. Raw external
`tsx` and `node --import tsx` invocations outside these launchers are unchanged.
Test wrapper runs end with a short `[test] passed|failed|skipped ... in ...` summary; Vitest's own duration line stays the per-shard detail.
| Command | What it does |
+283 -283
View File
@@ -1497,16 +1497,16 @@
"./cli-entry": "./openclaw.mjs"
},
"scripts": {
"android:assemble": "node --import tsx scripts/run-android-gradle.mts :app:assemblePlayDebug :wear:assembleDebug :wear-shared:assembleDebug",
"android:assemble:third-party": "node --import tsx scripts/run-android-gradle.mts :app:assembleThirdPartyDebug",
"android:assemble": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:assemblePlayDebug :wear:assembleDebug :wear-shared:assembleDebug",
"android:assemble:third-party": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:assembleThirdPartyDebug",
"android:bundle:release": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android play_store_archive'",
"android:format": "cd apps/android && ./gradlew :app:ktlintFormat :benchmark:ktlintFormat :wear:ktlintFormat :wear-shared:ktlintFormat",
"android:install": "node --import tsx scripts/run-android-gradle.mts :app:installPlayDebug",
"android:install:third-party": "node --import tsx scripts/run-android-gradle.mts :app:installThirdPartyDebug",
"android:install": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:installPlayDebug",
"android:install:third-party": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:installThirdPartyDebug",
"android:lint": "cd apps/android && ./gradlew :app:ktlintCheck :benchmark:ktlintCheck :wear:ktlintCheck :wear-shared:ktlintCheck",
"android:lint:android": "node --import tsx scripts/run-android-gradle.mts :app:lintPlayDebug :app:lintThirdPartyDebug :wear:lintDebug :wear-shared:lintDebug",
"android:run": "node --import tsx scripts/run-android-gradle.mts :app:runPlayDebug",
"android:run:third-party": "node --import tsx scripts/run-android-gradle.mts :app:runThirdPartyDebug",
"android:lint:android": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:lintPlayDebug :app:lintThirdPartyDebug :wear:lintDebug :wear-shared:lintDebug",
"android:run": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:runPlayDebug",
"android:run:third-party": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:runThirdPartyDebug",
"android:release": "bash scripts/android-release.sh",
"android:release:archive": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android play_store_archive'",
"android:release:auth:check": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android auth_check'",
@@ -1518,100 +1518,100 @@
"android:release:signing:sync:push": "bash -lc 'source ./scripts/lib/android-fastlane.sh && cd apps/android && run_android_fastlane android signing_sync_push'",
"android:release:upload": "bash scripts/android-release-upload.sh",
"android:screenshots": "bash scripts/android-screenshots.sh",
"android:test": "node --import tsx scripts/run-android-gradle.mts :app:testPlayDebugUnitTest :wear:testDebugUnitTest :wear-shared:testDebugUnitTest",
"android:test:integration": "node --import tsx scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_ANDROID_NODE=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.live.config.ts src/gateway/android-node.capabilities.live.test.ts",
"android:test:third-party": "node --import tsx scripts/run-android-gradle.mts :app:testThirdPartyDebugUnitTest",
"android:version": "node --import tsx scripts/android-version.ts --json",
"android:version:check": "node --import tsx scripts/android-sync-versioning.ts --check",
"android:version:pin": "node --import tsx scripts/android-pin-version.ts",
"android:version:sync": "node --import tsx scripts/android-sync-versioning.ts --write",
"audit:seams": "node --import tsx scripts/audit-seams.mts",
"build": "node --import tsx scripts/build-all.mts",
"build:ci-artifacts": "node --import tsx scripts/build-all.mts ciArtifacts",
"build:docker": "pnpm plugins:assets:build && node --import tsx scripts/tsdown-build.mts && node --import tsx scripts/check-cli-bootstrap-imports.mts && node scripts/runtime-postbuild.mjs && node --import tsx scripts/build-stamp.mts && node --import tsx scripts/runtime-postbuild-stamp.mts && pnpm plugins:assets:copy && node --import tsx scripts/write-build-info.ts && node --import tsx scripts/write-cli-startup-metadata.ts",
"build:package": "node --import tsx scripts/build-all.mts package",
"android:test": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:testPlayDebugUnitTest :wear:testDebugUnitTest :wear-shared:testDebugUnitTest",
"android:test:integration": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_ANDROID_NODE=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.live.config.ts src/gateway/android-node.capabilities.live.test.ts",
"android:test:third-party": "node --import ./scripts/tsx.mjs scripts/run-android-gradle.mts :app:testThirdPartyDebugUnitTest",
"android:version": "node --import ./scripts/tsx.mjs scripts/android-version.ts --json",
"android:version:check": "node --import ./scripts/tsx.mjs scripts/android-sync-versioning.ts --check",
"android:version:pin": "node --import ./scripts/tsx.mjs scripts/android-pin-version.ts",
"android:version:sync": "node --import ./scripts/tsx.mjs scripts/android-sync-versioning.ts --write",
"audit:seams": "node --import ./scripts/tsx.mjs scripts/audit-seams.mts",
"build": "node --import ./scripts/tsx.mjs scripts/build-all.mts",
"build:ci-artifacts": "node --import ./scripts/tsx.mjs scripts/build-all.mts ciArtifacts",
"build:docker": "pnpm plugins:assets:build && node --import ./scripts/tsx.mjs scripts/tsdown-build.mts && node --import ./scripts/tsx.mjs scripts/check-cli-bootstrap-imports.mts && node scripts/runtime-postbuild.mjs && node --import ./scripts/tsx.mjs scripts/build-stamp.mts && node --import ./scripts/tsx.mjs scripts/runtime-postbuild-stamp.mts && pnpm plugins:assets:copy && node --import ./scripts/tsx.mjs scripts/write-build-info.ts && node --import ./scripts/tsx.mjs scripts/write-cli-startup-metadata.ts",
"build:package": "node --import ./scripts/tsx.mjs scripts/build-all.mts package",
"build:plugin-sdk:dts": "node scripts/run-tsgo.mjs -p tsconfig.plugin-sdk.dts.json --declaration true",
"build:plugin-sdk:strict-smoke": "node --import tsx scripts/tsdown-build.mts && node scripts/runtime-postbuild.mjs && node --import tsx scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/check-plugin-sdk-exports.mts",
"build:strict-smoke": "pnpm plugins:assets:build && node --import tsx scripts/tsdown-build.mts && node --import tsx scripts/check-cli-bootstrap-imports.mts && node scripts/runtime-postbuild.mjs && node --import tsx scripts/build-stamp.mts && node --import tsx scripts/runtime-postbuild-stamp.mts && node --import tsx scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/check-plugin-sdk-exports.mts",
"canvas:a2ui:bundle": "node --import tsx scripts/bundle-a2ui.mts",
"build:plugin-sdk:strict-smoke": "node --import ./scripts/tsx.mjs scripts/tsdown-build.mts && node scripts/runtime-postbuild.mjs && node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import ./scripts/tsx.mjs scripts/write-plugin-sdk-entry-dts.ts && node --import ./scripts/tsx.mjs scripts/check-plugin-sdk-exports.mts",
"build:strict-smoke": "pnpm plugins:assets:build && node --import ./scripts/tsx.mjs scripts/tsdown-build.mts && node --import ./scripts/tsx.mjs scripts/check-cli-bootstrap-imports.mts && node scripts/runtime-postbuild.mjs && node --import ./scripts/tsx.mjs scripts/build-stamp.mts && node --import ./scripts/tsx.mjs scripts/runtime-postbuild-stamp.mts && node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import ./scripts/tsx.mjs scripts/write-plugin-sdk-entry-dts.ts && node --import ./scripts/tsx.mjs scripts/check-plugin-sdk-exports.mts",
"canvas:a2ui:bundle": "node --import ./scripts/tsx.mjs scripts/bundle-a2ui.mts",
"channels:catalog:check": "node scripts/write-official-channel-catalog.mjs --check",
"channels:catalog:gen": "node scripts/write-official-channel-catalog.mjs --write",
"changed:lanes": "node scripts/changed-lanes.mjs",
"check": "node --import tsx scripts/check.mts",
"check": "node --import ./scripts/tsx.mjs scripts/check.mts",
"check:architecture": "pnpm check:import-cycles && pnpm check:madge-import-cycles && pnpm check:deprecated-api-usage && pnpm check:wrapper-shadowing && pnpm check:deprecated-jsdoc && pnpm db:kysely:check && pnpm lint:kysely && pnpm check:database-first-legacy-stores",
"check:assertion-safety": "node --import tsx scripts/check-assertion-safety-ratchet.mts",
"check:base-config-schema": "node --import tsx scripts/generate-base-config-schema.ts --check",
"check:bundled-channel-config-metadata": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --check",
"check:assertion-safety": "node --import ./scripts/tsx.mjs scripts/check-assertion-safety-ratchet.mts",
"check:base-config-schema": "node --import ./scripts/tsx.mjs scripts/generate-base-config-schema.ts --check",
"check:bundled-channel-config-metadata": "node --import ./scripts/tsx.mjs scripts/generate-bundled-channel-config-metadata.ts --check",
"check:changed": "node scripts/check-changed.mjs",
"check:changelog-attributions": "node --import tsx scripts/check-changelog-attributions.mts",
"check:coercion-helpers": "node --import tsx scripts/check-coercion-helper-declarations.mts",
"check:database-first-legacy-stores": "node --import tsx scripts/check-database-first-legacy-stores.mts",
"check:deprecated-api-usage": "node --import tsx scripts/check-deprecated-api-usage.mts",
"check:deprecated-jsdoc": "node --import tsx scripts/check-deprecated-jsdoc.mts",
"check:doctor-deprecation-registry": "node --import tsx scripts/check-doctor-deprecation-registry.ts",
"check:changelog-attributions": "node --import ./scripts/tsx.mjs scripts/check-changelog-attributions.mts",
"check:coercion-helpers": "node --import ./scripts/tsx.mjs scripts/check-coercion-helper-declarations.mts",
"check:database-first-legacy-stores": "node --import ./scripts/tsx.mjs scripts/check-database-first-legacy-stores.mts",
"check:deprecated-api-usage": "node --import ./scripts/tsx.mjs scripts/check-deprecated-api-usage.mts",
"check:deprecated-jsdoc": "node --import ./scripts/tsx.mjs scripts/check-deprecated-jsdoc.mts",
"check:doctor-deprecation-registry": "node --import ./scripts/tsx.mjs scripts/check-doctor-deprecation-registry.ts",
"check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-mdx && pnpm docs:check-i18n-glossary && pnpm docs:check-links && pnpm docs:check-config-examples",
"check:env-var-count": "node --import tsx scripts/check-env-var-count.mts",
"check:host-env-policy:swift": "node --import tsx scripts/generate-host-env-security-policy-swift.mts --check",
"check:import-cycles": "node --import tsx scripts/check-import-cycles.ts",
"check:max-lines-ratchet": "node --import tsx scripts/check-max-lines-ratchet.mts",
"check:madge-import-cycles": "node --import tsx scripts/check-madge-import-cycles.ts",
"check:media-download-helpers": "node --import tsx scripts/check-media-download-helper-roundtrip.mts",
"check:env-var-count": "node --import ./scripts/tsx.mjs scripts/check-env-var-count.mts",
"check:host-env-policy:swift": "node --import ./scripts/tsx.mjs scripts/generate-host-env-security-policy-swift.mts --check",
"check:import-cycles": "node --import ./scripts/tsx.mjs scripts/check-import-cycles.ts",
"check:max-lines-ratchet": "node --import ./scripts/tsx.mjs scripts/check-max-lines-ratchet.mts",
"check:madge-import-cycles": "node --import ./scripts/tsx.mjs scripts/check-madge-import-cycles.ts",
"check:media-download-helpers": "node --import ./scripts/tsx.mjs scripts/check-media-download-helper-roundtrip.mts",
"check:no-conflict-markers": "node scripts/check-no-conflict-markers.mjs",
"check:no-runtime-action-load-config": "node --import tsx scripts/check-no-runtime-action-load-config.mts",
"check:no-runtime-action-load-config": "node --import ./scripts/tsx.mjs scripts/check-no-runtime-action-load-config.mts",
"check:opengrep-rule-metadata": "node security/opengrep/check-rule-metadata.mjs",
"check:protocol-coverage": "node scripts/check-protocol-event-coverage.mjs",
"check:runtime-sidecar-loaders": "node --import tsx scripts/check-runtime-sidecar-loaders.mts",
"check:runtime-sidecar-loaders": "node --import ./scripts/tsx.mjs scripts/check-runtime-sidecar-loaders.mts",
"check:script-erasability": "node --disable-warning=ExperimentalWarning scripts/check-script-erasability.mjs",
"check:static-import-sccs": "pnpm check:madge-import-cycles",
"check:temp-path-guardrails": "node --import tsx scripts/check-temp-path-guardrails.ts",
"check:wrapper-shadowing": "node --import tsx scripts/check-wrapper-shadowing.mts",
"check:temp-path-guardrails": "node --import ./scripts/tsx.mjs scripts/check-temp-path-guardrails.ts",
"check:wrapper-shadowing": "node --import ./scripts/tsx.mjs scripts/check-wrapper-shadowing.mts",
"check:test-types": "pnpm tsgo:test",
"check:timed": "node --import tsx scripts/check-timed.mts",
"check:timed:all-types": "node --import tsx scripts/check-timed.mts --include-test-types",
"check:timed:architecture": "node --import tsx scripts/check-timed.mts --include-architecture",
"check:workflows": "node --import tsx scripts/check-workflows.mts",
"check:timed": "node --import ./scripts/tsx.mjs scripts/check-timed.mts",
"check:timed:all-types": "node --import ./scripts/tsx.mjs scripts/check-timed.mts --include-test-types",
"check:timed:architecture": "node --import ./scripts/tsx.mjs scripts/check-timed.mts --include-architecture",
"check:workflows": "node --import ./scripts/tsx.mjs scripts/check-workflows.mts",
"ci:full-release": "node scripts/full-release-validation-at-sha.mjs",
"ci:timings": "node scripts/ci-run-timings.mjs --latest-main",
"ci:timings:recent": "node scripts/ci-run-timings.mjs --recent 10",
"ci:timings:trend": "node scripts/ci-run-timings.mjs --trend-hours 72 --compare-hours 12",
"clean:dist": "node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"",
"codex-app-server:protocol:check": "node --import tsx scripts/check-codex-app-server-protocol.ts",
"codex-app-server:protocol:sync": "node --import tsx scripts/sync-codex-app-server-protocol.ts",
"codex-supervisor:mcp": "node --import tsx src/mcp/codex-supervision-tools-serve.ts",
"codex:mcp": "node --import tsx src/mcp/codex-supervision-tools-serve.ts",
"config:channels:check": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --check",
"config:channels:gen": "node --import tsx scripts/generate-bundled-channel-config-metadata.ts --write",
"config:docs:check": "node --import tsx scripts/generate-config-doc-baseline.ts --check",
"config:docs:gen": "node --import tsx scripts/generate-config-doc-baseline.ts --write",
"config:schema:check": "node --import tsx scripts/generate-base-config-schema.ts --check",
"config:schema:gen": "node --import tsx scripts/generate-base-config-schema.ts --write",
"codex-app-server:protocol:check": "node --import ./scripts/tsx.mjs scripts/check-codex-app-server-protocol.ts",
"codex-app-server:protocol:sync": "node --import ./scripts/tsx.mjs scripts/sync-codex-app-server-protocol.ts",
"codex-supervisor:mcp": "node --import ./scripts/tsx.mjs src/mcp/codex-supervision-tools-serve.ts",
"codex:mcp": "node --import ./scripts/tsx.mjs src/mcp/codex-supervision-tools-serve.ts",
"config:channels:check": "node --import ./scripts/tsx.mjs scripts/generate-bundled-channel-config-metadata.ts --check",
"config:channels:gen": "node --import ./scripts/tsx.mjs scripts/generate-bundled-channel-config-metadata.ts --write",
"config:docs:check": "node --import ./scripts/tsx.mjs scripts/generate-config-doc-baseline.ts --check",
"config:docs:gen": "node --import ./scripts/tsx.mjs scripts/generate-config-doc-baseline.ts --write",
"config:schema:check": "node --import ./scripts/tsx.mjs scripts/generate-base-config-schema.ts --check",
"config:schema:gen": "node --import ./scripts/tsx.mjs scripts/generate-base-config-schema.ts --write",
"crabbox:hydrate": "node scripts/crabbox-wrapper.mjs actions hydrate",
"crabbox:run": "node scripts/crabbox-wrapper.mjs run",
"crabbox:stop": "node scripts/crabbox-wrapper.mjs stop",
"crabbox:warmup": "node scripts/crabbox-wrapper.mjs warmup",
"deadcode:dependencies": "pnpm deadcode:full",
"deadcode:exports": "node --import tsx scripts/check-deadcode-exports.mts",
"deadcode:exports": "node --import ./scripts/tsx.mjs scripts/check-deadcode-exports.mts",
"deadcode:full": "pnpm --config.minimum-release-age=0 dlx --package knip@6.32.2 knip --config config/knip.config.ts --production --no-progress --reporter compact --no-config-hints --exclude duplicates && pnpm --config.minimum-release-age=0 dlx --package knip@6.32.2 knip --config config/knip.all-exports.config.ts --no-progress --reporter compact --no-config-hints --exports --exclude duplicates",
"deadcode:knip": "pnpm --config.minimum-release-age=0 dlx --package knip@6.32.2 knip --config config/knip.config.ts --production --no-progress --reporter compact --files --dependencies",
"deadcode:report": "pnpm deadcode:full && pnpm deadcode:exports",
"deadcode:unused-files": "node --import tsx scripts/check-deadcode-unused-files.mts",
"deps:root-ownership": "node --import tsx scripts/root-dependency-ownership-audit.mts",
"deps:root-ownership:check": "node --import tsx scripts/root-dependency-ownership-audit.mts --check",
"deps:changes:report": "node --import tsx scripts/dependency-changes-report.mts",
"deps:patches:check": "node --import tsx scripts/check-package-patches.mts",
"deps:pins:check": "node --import tsx scripts/check-dependency-pins.mts",
"deadcode:unused-files": "node --import ./scripts/tsx.mjs scripts/check-deadcode-unused-files.mts",
"deps:root-ownership": "node --import ./scripts/tsx.mjs scripts/root-dependency-ownership-audit.mts",
"deps:root-ownership:check": "node --import ./scripts/tsx.mjs scripts/root-dependency-ownership-audit.mts --check",
"deps:changes:report": "node --import ./scripts/tsx.mjs scripts/dependency-changes-report.mts",
"deps:patches:check": "node --import ./scripts/tsx.mjs scripts/check-package-patches.mts",
"deps:pins:check": "node --import ./scripts/tsx.mjs scripts/check-dependency-pins.mts",
"deps:npm-lock:check": "node scripts/generate-npm-package-lock.mjs --all",
"deps:npm-lock:check:changed": "node scripts/generate-npm-package-lock.mjs --changed",
"deps:ownership-surface:check": "node --import tsx scripts/dependency-ownership-surface-report.mts --check",
"deps:ownership-surface:report": "node --import tsx scripts/dependency-ownership-surface-report.mts",
"deps:transitive-risk:report": "node --import tsx scripts/transitive-manifest-risk-report.mts",
"deps:vuln:gate": "node --import tsx scripts/dependency-vulnerability-gate.mts",
"db:kysely:check": "node --import tsx scripts/generate-kysely-types.mts --verify",
"db:kysely:gen": "node --import tsx scripts/generate-kysely-types.mts",
"deps:ownership-surface:check": "node --import ./scripts/tsx.mjs scripts/dependency-ownership-surface-report.mts --check",
"deps:ownership-surface:report": "node --import ./scripts/tsx.mjs scripts/dependency-ownership-surface-report.mts",
"deps:transitive-risk:report": "node --import ./scripts/tsx.mjs scripts/transitive-manifest-risk-report.mts",
"deps:vuln:gate": "node --import ./scripts/tsx.mjs scripts/dependency-vulnerability-gate.mts",
"db:kysely:check": "node --import ./scripts/tsx.mjs scripts/generate-kysely-types.mts --verify",
"db:kysely:gen": "node --import ./scripts/tsx.mjs scripts/generate-kysely-types.mts",
"dev": "node scripts/run-node.mjs",
"dev:ui:mock": "node --import tsx scripts/control-ui-mock-dev.ts",
"dev:ui:mock": "node --import ./scripts/tsx.mjs scripts/control-ui-mock-dev.ts",
"docs:check-config-examples": "node scripts/check-docs-config-examples.mjs",
"docs:check-i18n-glossary": "node --import tsx scripts/check-docs-i18n-glossary.mts",
"docs:check-i18n-glossary": "node --import ./scripts/tsx.mjs scripts/check-docs-i18n-glossary.mts",
"docs:check-links": "node scripts/docs-link-audit.mjs",
"docs:check-links:anchors": "node scripts/docs-link-audit.mjs --anchors",
"docs:check-mdx": "node scripts/check-docs-mdx.mjs docs README.md",
@@ -1620,8 +1620,8 @@
"docs:map:gen": "node scripts/docs-list.js --headings",
"docs:spellcheck": "bash scripts/docs-spellcheck.sh",
"docs:spellcheck:fix": "bash scripts/docs-spellcheck.sh --write",
"maturity:check": "node --import tsx scripts/qa/render-maturity-docs.ts --check",
"maturity:render": "node --import tsx scripts/qa/render-maturity-docs.ts",
"maturity:check": "node --import ./scripts/tsx.mjs scripts/qa/render-maturity-docs.ts --check",
"maturity:render": "node --import ./scripts/tsx.mjs scripts/qa/render-maturity-docs.ts",
"dup:check": "node scripts/check-duplicates.mjs",
"dup:check:coverage": "node scripts/check-duplicates.mjs --coverage",
"dup:check:json": "node scripts/check-duplicates.mjs --json",
@@ -1629,16 +1629,16 @@
"format:all": "pnpm format && pnpm format:swift",
"format:check": "oxfmt --check",
"format:diff": "oxfmt --write --threads=1 && git --no-pager diff",
"format:docs": "node --import tsx scripts/format-docs.mts",
"format:docs:check": "node --import tsx scripts/format-docs.mts --check",
"format:docs": "node --import ./scripts/tsx.mjs scripts/format-docs.mts",
"format:docs:check": "node --import ./scripts/tsx.mjs scripts/format-docs.mts --check",
"format:fix": "oxfmt --write --threads=1",
"format:swift": "./scripts/format-swift.sh",
"gateway:dev": "node --import tsx scripts/run-with-env.mts OPENCLAW_SKIP_CHANNELS=1 -- node scripts/run-node.mjs --dev gateway",
"gateway:dev:reset": "node --import tsx scripts/run-with-env.mts OPENCLAW_SKIP_CHANNELS=1 -- node scripts/run-node.mjs --dev gateway --reset",
"gateway:watch": "node --import tsx scripts/gateway-watch-tmux.mts gateway --force",
"gateway:dev": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_SKIP_CHANNELS=1 -- node scripts/run-node.mjs --dev gateway",
"gateway:dev:reset": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_SKIP_CHANNELS=1 -- node scripts/run-node.mjs --dev gateway --reset",
"gateway:watch": "node --import ./scripts/tsx.mjs scripts/gateway-watch-tmux.mts gateway --force",
"gateway:watch:raw": "node scripts/watch-node.mjs gateway --force",
"gen:host-env-policy:swift": "node --import tsx scripts/generate-host-env-security-policy-swift.mts --write",
"ghsa:patch": "node --import tsx scripts/ghsa-patch.mts",
"gen:host-env-policy:swift": "node --import ./scripts/tsx.mjs scripts/generate-host-env-security-policy-swift.mts --write",
"ghsa:patch": "node --import ./scripts/tsx.mjs scripts/ghsa-patch.mts",
"ios:app-review-notes:pdf": "xcrun swift scripts/ios-app-review-notes-pdf.swift apps/ios/APP-REVIEW-NOTES.md apps/ios/build/app-review/APP-REVIEW-NOTES.pdf",
"ios:build": "bash -c 'export PATH=\"$PATH:/opt/homebrew/bin:/usr/local/bin\"; ./scripts/ios-configure-signing.sh && ./scripts/ios-write-version-xcconfig.sh && node scripts/ios-write-swift-filelist.mjs && cd apps/ios && xcodegen generate && xcodebuild -project OpenClaw.xcodeproj -scheme OpenClaw -destination \"${IOS_DEST:-generic/platform=iOS Simulator}\" -configuration Debug build'",
"ios:filelist:gen": "node scripts/ios-write-swift-filelist.mjs",
@@ -1656,155 +1656,155 @@
"ios:release:upload": "bash scripts/ios-release-upload.sh",
"ios:run": "bash scripts/ios-run.sh",
"ios:screenshots": "bash scripts/ios-screenshots.sh",
"ios:version": "node --import tsx scripts/ios-version.ts --json",
"ios:version:check": "node --import tsx scripts/ios-sync-versioning.ts --check",
"ios:version:sync": "node --import tsx scripts/ios-sync-versioning.ts --write",
"leak:embedded-run": "node --import tsx --expose-gc scripts/embedded-run-abort-leak.ts",
"lint": "node --import tsx scripts/run-lint.mts",
"lint:agent:ingress-owner": "node --import tsx scripts/check-ingress-agent-owner-context.mts",
"ios:version": "node --import ./scripts/tsx.mjs scripts/ios-version.ts --json",
"ios:version:check": "node --import ./scripts/tsx.mjs scripts/ios-sync-versioning.ts --check",
"ios:version:sync": "node --import ./scripts/tsx.mjs scripts/ios-sync-versioning.ts --write",
"leak:embedded-run": "node --import ./scripts/tsx.mjs --expose-gc scripts/embedded-run-abort-leak.ts",
"lint": "node --import ./scripts/tsx.mjs scripts/run-lint.mts",
"lint:agent:ingress-owner": "node --import ./scripts/tsx.mjs scripts/check-ingress-agent-owner-context.mts",
"lint:all": "node scripts/run-oxlint.mjs",
"lint:apps": "pnpm lint:swift",
"lint:auth:no-pairing-store-group": "node --import tsx scripts/check-no-pairing-store-group-auth.mts",
"lint:auth:pairing-account-scope": "node --import tsx scripts/check-pairing-account-scope.mts",
"lint:core": "node --import tsx scripts/run-oxlint-shards.mts --only=core",
"lint:docker-e2e": "node --import tsx scripts/check-docker-e2e-boundaries.mts",
"lint:kysely": "node --import tsx scripts/check-kysely-guardrails.mts",
"lint:auth:no-pairing-store-group": "node --import ./scripts/tsx.mjs scripts/check-no-pairing-store-group-auth.mts",
"lint:auth:pairing-account-scope": "node --import ./scripts/tsx.mjs scripts/check-pairing-account-scope.mts",
"lint:core": "node --import ./scripts/tsx.mjs scripts/run-oxlint-shards.mts --only=core",
"lint:docker-e2e": "node --import ./scripts/tsx.mjs scripts/check-docker-e2e-boundaries.mts",
"lint:kysely": "node --import ./scripts/tsx.mjs scripts/check-kysely-guardrails.mts",
"lint:docs": "pnpm dlx --config.resolution-mode=highest markdownlint-cli2 --config config/markdownlint-cli2.jsonc",
"lint:docs:fix": "pnpm dlx --config.resolution-mode=highest markdownlint-cli2 --config config/markdownlint-cli2.jsonc --fix",
"lint:extensions:no-deprecated-channel-access": "node --import tsx scripts/check-no-deprecated-channel-access.ts",
"lint:extensions:telegram-grammy-types": "node --import tsx scripts/check-telegram-grammy-types-imports.mts",
"lint:extensions:no-deprecated-channel-access": "node --import ./scripts/tsx.mjs scripts/check-no-deprecated-channel-access.ts",
"lint:extensions:telegram-grammy-types": "node --import ./scripts/tsx.mjs scripts/check-telegram-grammy-types-imports.mts",
"lint:extensions": "node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.extensions.json extensions",
"lint:extensions:no-guarded-wildcard-reexports": "node --import tsx scripts/check-extension-wildcard-reexports.mts",
"lint:extensions:no-normalization-core-bypass": "node --import tsx scripts/check-extension-plugin-sdk-boundary.mts --mode=normalization-core-bypass",
"lint:extensions:no-plugin-sdk-wildcard-reexports": "node --import tsx scripts/check-plugin-sdk-wildcard-reexports.mts",
"lint:extensions:no-relative-outside-package": "node --import tsx scripts/check-extension-plugin-sdk-boundary.mts --mode=relative-outside-package",
"lint:extensions:no-src-outside-plugin-sdk": "node --import tsx scripts/check-extension-plugin-sdk-boundary.mts --mode=src-outside-plugin-sdk",
"lint:extensions:no-guarded-wildcard-reexports": "node --import ./scripts/tsx.mjs scripts/check-extension-wildcard-reexports.mts",
"lint:extensions:no-normalization-core-bypass": "node --import ./scripts/tsx.mjs scripts/check-extension-plugin-sdk-boundary.mts --mode=normalization-core-bypass",
"lint:extensions:no-plugin-sdk-wildcard-reexports": "node --import ./scripts/tsx.mjs scripts/check-plugin-sdk-wildcard-reexports.mts",
"lint:extensions:no-relative-outside-package": "node --import ./scripts/tsx.mjs scripts/check-extension-plugin-sdk-boundary.mts --mode=relative-outside-package",
"lint:extensions:no-src-outside-plugin-sdk": "node --import ./scripts/tsx.mjs scripts/check-extension-plugin-sdk-boundary.mts --mode=src-outside-plugin-sdk",
"lint:fix": "node scripts/run-oxlint.mjs --fix && pnpm format",
"lint:plugins:no-extension-imports": "node --import tsx scripts/check-plugin-extension-import-boundary.mts",
"lint:plugins:no-extension-src-imports": "node --import tsx scripts/check-no-extension-src-imports.ts",
"lint:plugins:no-extension-test-core-imports": "node --import tsx scripts/check-no-extension-test-core-imports.ts",
"lint:plugins:no-monolithic-plugin-sdk-entry-imports": "node --import tsx scripts/check-no-monolithic-plugin-sdk-entry-imports.ts",
"lint:plugins:no-extension-imports": "node --import ./scripts/tsx.mjs scripts/check-plugin-extension-import-boundary.mts",
"lint:plugins:no-extension-src-imports": "node --import ./scripts/tsx.mjs scripts/check-no-extension-src-imports.ts",
"lint:plugins:no-extension-test-core-imports": "node --import ./scripts/tsx.mjs scripts/check-no-extension-test-core-imports.ts",
"lint:plugins:no-monolithic-plugin-sdk-entry-imports": "node --import ./scripts/tsx.mjs scripts/check-no-monolithic-plugin-sdk-entry-imports.ts",
"lint:plugins:no-register-http-handler": "node scripts/run-oxlint.mjs --openclaw-focused-config --config config/oxlint/boundary-guards.json src extensions",
"lint:plugins:plugin-sdk-subpaths-exported": "node --import tsx scripts/check-plugin-sdk-subpath-exports.mts",
"lint:plugins:plugin-sdk-subpaths-exported": "node --import ./scripts/tsx.mjs scripts/check-plugin-sdk-subpath-exports.mts",
"lint:no-chained-type-assertions": "node scripts/run-oxlint.mjs --openclaw-focused-config --config config/oxlint/boundary-guards.json src extensions packages ui/src",
"lint:no-widen-then-assert": "node scripts/run-oxlint.mjs --openclaw-focused-config --config config/oxlint/boundary-guards.json src extensions packages ui/src",
"lint:scripts": "pnpm lint:docker-e2e && pnpm lint:tmp:no-raw-http2-imports && node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.scripts.json scripts",
"lint:swift": "./scripts/lint-swift.sh",
"lint:tmp:channel-agnostic-boundaries": "node --import tsx scripts/check-channel-agnostic-boundaries.mts",
"lint:tmp:dynamic-import-warts": "node --import tsx scripts/check-dynamic-import-warts.mts",
"lint:tmp:export-name-collisions": "node --import tsx scripts/check-export-name-collisions.mts",
"lint:tmp:no-random-messaging": "node --import tsx scripts/check-no-random-messaging-tmp.mts",
"lint:tmp:no-raw-channel-fetch": "node --import tsx scripts/check-no-raw-channel-fetch.mts",
"lint:tmp:no-raw-http2-imports": "node --import tsx scripts/check-no-raw-http2-imports.mts",
"lint:tmp:session-accessor-boundary": "node --import tsx scripts/check-session-accessor-boundary.mts",
"lint:tmp:session-accessor-boundary:gen": "node --import tsx scripts/check-session-accessor-boundary.mts --update-debt-baseline",
"lint:tmp:session-transcript-reader-boundary": "node --import tsx scripts/check-session-transcript-reader-boundary.mts",
"lint:tmp:sqlite-transaction-boundary": "node --import tsx scripts/check-sqlite-transaction-boundary.mts",
"lint:tmp:tsgo-core-boundary": "node --import tsx scripts/check-tsgo-core-boundary.mts",
"lint:tmp:channel-agnostic-boundaries": "node --import ./scripts/tsx.mjs scripts/check-channel-agnostic-boundaries.mts",
"lint:tmp:dynamic-import-warts": "node --import ./scripts/tsx.mjs scripts/check-dynamic-import-warts.mts",
"lint:tmp:export-name-collisions": "node --import ./scripts/tsx.mjs scripts/check-export-name-collisions.mts",
"lint:tmp:no-random-messaging": "node --import ./scripts/tsx.mjs scripts/check-no-random-messaging-tmp.mts",
"lint:tmp:no-raw-channel-fetch": "node --import ./scripts/tsx.mjs scripts/check-no-raw-channel-fetch.mts",
"lint:tmp:no-raw-http2-imports": "node --import ./scripts/tsx.mjs scripts/check-no-raw-http2-imports.mts",
"lint:tmp:session-accessor-boundary": "node --import ./scripts/tsx.mjs scripts/check-session-accessor-boundary.mts",
"lint:tmp:session-accessor-boundary:gen": "node --import ./scripts/tsx.mjs scripts/check-session-accessor-boundary.mts --update-debt-baseline",
"lint:tmp:session-transcript-reader-boundary": "node --import ./scripts/tsx.mjs scripts/check-session-transcript-reader-boundary.mts",
"lint:tmp:sqlite-transaction-boundary": "node --import ./scripts/tsx.mjs scripts/check-sqlite-transaction-boundary.mts",
"lint:tmp:tsgo-core-boundary": "node --import ./scripts/tsx.mjs scripts/check-tsgo-core-boundary.mts",
"lint:ui:i18n": "pnpm ui:i18n:verify",
"lint:ui:lit": "lit-analyzer \"ui/src/**/*.ts\" --quiet",
"lint:ui:no-raw-window-open": "node scripts/run-oxlint.mjs --openclaw-focused-config --config config/oxlint/boundary-guards.json ui/src",
"lint:ui:styles": "stylelint --config config/stylelint.config.mjs \"ui/src/**/*.css\" \"ui/src/**/*.ts\" \"ui/public/themes/*.css\"",
"lint:web-fetch-provider-boundaries": "node --import tsx scripts/check-web-fetch-provider-boundaries.mts",
"lint:webhook:no-low-level-body-read": "node --import tsx scripts/check-webhook-auth-body-order.mts",
"lint:web-fetch-provider-boundaries": "node --import ./scripts/tsx.mjs scripts/check-web-fetch-provider-boundaries.mts",
"lint:webhook:no-low-level-body-read": "node --import ./scripts/tsx.mjs scripts/check-webhook-auth-body-order.mts",
"mac:open": "open dist/OpenClaw.app",
"mac:package": "bash scripts/package-mac-app.sh",
"mac:restart": "bash scripts/restart-mac.sh",
"mobile:release:preflight": "node --import tsx scripts/mobile-release-ref.ts preflight",
"mobile:release:record": "node --import tsx scripts/mobile-release-ref.ts record",
"mobile:release:resolve": "node --import tsx scripts/mobile-release-ref.ts resolve",
"mobile:release:preflight": "node --import ./scripts/tsx.mjs scripts/mobile-release-ref.ts preflight",
"mobile:release:record": "node --import ./scripts/tsx.mjs scripts/mobile-release-ref.ts record",
"mobile:release:resolve": "node --import ./scripts/tsx.mjs scripts/mobile-release-ref.ts resolve",
"openclaw": "node scripts/run-node.mjs",
"openclaw:rpc": "node scripts/run-node.mjs agent --mode rpc --json",
"perf:web-fetch": "node --import tsx scripts/bench-web-fetch.ts",
"perf:kova:summary": "node --import tsx scripts/kova-ci-summary.mts",
"perf:source:summary": "node --import tsx scripts/openclaw-performance-source-summary.mts",
"plugin-sdk:api:diff": "node --max-old-space-size=8192 --import tsx scripts/plugin-sdk-api-diff.mts",
"plugin-sdk:check-exports": "node --import tsx scripts/sync-plugin-sdk-exports.mts --check",
"plugin-sdk:surface": "node --max-old-space-size=8192 --import tsx scripts/plugin-sdk-surface-report.mts",
"plugin-sdk:surface:check": "node --max-old-space-size=8192 --import tsx scripts/plugin-sdk-surface-report.mts --check",
"plugin-sdk:sync-exports": "node --import tsx scripts/sync-plugin-sdk-exports.mts",
"plugin-sdk:usage": "node --max-old-space-size=8192 --import tsx scripts/analyze-plugin-sdk-usage.ts",
"policy:config-coverage": "node --import tsx scripts/check-policy-config-coverage.ts",
"plugins:boundary-report": "node --import tsx scripts/plugin-boundary-report.ts",
"plugins:boundary-report:ci": "node --import tsx scripts/plugin-boundary-report.ts --summary --fail-on-eligible-compat",
"plugins:boundary-report:json": "node --import tsx scripts/plugin-boundary-report.ts --json",
"plugins:boundary-report:summary": "node --import tsx scripts/plugin-boundary-report.ts --summary",
"plugins:assets:build": "node --import tsx scripts/bundled-plugin-assets.mts --phase build",
"plugins:assets:check": "node --import tsx scripts/bundled-plugin-assets.mts --phase build --check",
"plugins:assets:copy": "node --import tsx scripts/bundled-plugin-assets.mts --phase copy",
"plugins:inventory:check": "node --import tsx scripts/generate-plugin-inventory-doc.mts --check",
"plugins:inventory:gen": "node --import tsx scripts/generate-plugin-inventory-doc.mts --write",
"plugins:sync": "node --import tsx scripts/sync-plugin-versions.ts",
"plugins:sync:check": "node --import tsx scripts/sync-plugin-versions.ts --check",
"perf:web-fetch": "node --import ./scripts/tsx.mjs scripts/bench-web-fetch.ts",
"perf:kova:summary": "node --import ./scripts/tsx.mjs scripts/kova-ci-summary.mts",
"perf:source:summary": "node --import ./scripts/tsx.mjs scripts/openclaw-performance-source-summary.mts",
"plugin-sdk:api:diff": "node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/plugin-sdk-api-diff.mts",
"plugin-sdk:check-exports": "node --import ./scripts/tsx.mjs scripts/sync-plugin-sdk-exports.mts --check",
"plugin-sdk:surface": "node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/plugin-sdk-surface-report.mts",
"plugin-sdk:surface:check": "node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/plugin-sdk-surface-report.mts --check",
"plugin-sdk:sync-exports": "node --import ./scripts/tsx.mjs scripts/sync-plugin-sdk-exports.mts",
"plugin-sdk:usage": "node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/analyze-plugin-sdk-usage.ts",
"policy:config-coverage": "node --import ./scripts/tsx.mjs scripts/check-policy-config-coverage.ts",
"plugins:boundary-report": "node --import ./scripts/tsx.mjs scripts/plugin-boundary-report.ts",
"plugins:boundary-report:ci": "node --import ./scripts/tsx.mjs scripts/plugin-boundary-report.ts --summary --fail-on-eligible-compat",
"plugins:boundary-report:json": "node --import ./scripts/tsx.mjs scripts/plugin-boundary-report.ts --json",
"plugins:boundary-report:summary": "node --import ./scripts/tsx.mjs scripts/plugin-boundary-report.ts --summary",
"plugins:assets:build": "node --import ./scripts/tsx.mjs scripts/bundled-plugin-assets.mts --phase build",
"plugins:assets:check": "node --import ./scripts/tsx.mjs scripts/bundled-plugin-assets.mts --phase build --check",
"plugins:assets:copy": "node --import ./scripts/tsx.mjs scripts/bundled-plugin-assets.mts --phase copy",
"plugins:inventory:check": "node --import ./scripts/tsx.mjs scripts/generate-plugin-inventory-doc.mts --check",
"plugins:inventory:gen": "node --import ./scripts/tsx.mjs scripts/generate-plugin-inventory-doc.mts --write",
"plugins:sync": "node --import ./scripts/tsx.mjs scripts/sync-plugin-versions.ts",
"plugins:sync:check": "node --import ./scripts/tsx.mjs scripts/sync-plugin-versions.ts --check",
"postinstall": "node scripts/postinstall-bundled-plugins.mjs",
"postpack": "node scripts/openclaw-postpack.mjs",
"preinstall": "node scripts/preinstall-package-manager-warning.mjs",
"prepack": "node --import tsx scripts/openclaw-prepack.ts",
"prepack": "node --import ./scripts/tsx.mjs scripts/openclaw-prepack.ts",
"prepare": "node scripts/prepare-git-hooks.mjs",
"prepush:ci": "bash scripts/prepush-ci.sh",
"probe:anthropic:prompt": "node --import tsx scripts/anthropic-prompt-probe.ts",
"prompt:snapshots:check": "node --import tsx scripts/generate-prompt-snapshots.ts --check",
"prompt:snapshots:gen": "node --import tsx scripts/generate-prompt-snapshots.ts --write",
"prompt:snapshots:sync-codex-model": "node --import tsx scripts/sync-codex-model-prompt-fixture.ts",
"protocol:check": "pnpm protocol-registry:check && pnpm protocol:gen && pnpm protocol:check:swift && pnpm protocol:gen:kotlin && node --import tsx scripts/check-protocol-since.mts && git diff --exit-code -- dist/protocol.schema.json apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayProtocol.kt apps/android/app/src/main/java/ai/openclaw/app/protocol/OpenClawProtocolConstants.kt",
"probe:anthropic:prompt": "node --import ./scripts/tsx.mjs scripts/anthropic-prompt-probe.ts",
"prompt:snapshots:check": "node --import ./scripts/tsx.mjs scripts/generate-prompt-snapshots.ts --check",
"prompt:snapshots:gen": "node --import ./scripts/tsx.mjs scripts/generate-prompt-snapshots.ts --write",
"prompt:snapshots:sync-codex-model": "node --import ./scripts/tsx.mjs scripts/sync-codex-model-prompt-fixture.ts",
"protocol:check": "pnpm protocol-registry:check && pnpm protocol:gen && pnpm protocol:check:swift && pnpm protocol:gen:kotlin && node --import ./scripts/tsx.mjs scripts/check-protocol-since.mts && git diff --exit-code -- dist/protocol.schema.json apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayProtocol.kt apps/android/app/src/main/java/ai/openclaw/app/protocol/OpenClawProtocolConstants.kt",
"protocol:check:kotlin": "pnpm protocol:gen:kotlin && git diff --exit-code -- apps/android/app/src/main/java/ai/openclaw/app/gateway/GatewayProtocol.kt apps/android/app/src/main/java/ai/openclaw/app/protocol/OpenClawProtocolConstants.kt",
"protocol:check:swift": "node --import tsx scripts/protocol-gen-swift.ts --check",
"protocol:gen": "node --import tsx scripts/protocol-gen.ts",
"protocol:gen:kotlin": "node --import tsx scripts/protocol-gen-kotlin.ts",
"protocol:gen:swift": "node --import tsx scripts/protocol-gen-swift.ts",
"protocol-registry:check": "node --import tsx scripts/check-protocol-registry.mts",
"protocol:check:swift": "node --import ./scripts/tsx.mjs scripts/protocol-gen-swift.ts --check",
"protocol:gen": "node --import ./scripts/tsx.mjs scripts/protocol-gen.ts",
"protocol:gen:kotlin": "node --import ./scripts/tsx.mjs scripts/protocol-gen-kotlin.ts",
"protocol:gen:swift": "node --import ./scripts/tsx.mjs scripts/protocol-gen-swift.ts",
"protocol-registry:check": "node --import ./scripts/tsx.mjs scripts/check-protocol-registry.mts",
"proxy:coverage": "node scripts/run-node.mjs proxy coverage",
"proxy:gateway": "node scripts/run-node.mjs proxy run -- node scripts/run-node.mjs gateway",
"proxy:install-ca": "node --import tsx scripts/proxy-install-ca.mts",
"proxy:install-ca": "node --import ./scripts/tsx.mjs scripts/proxy-install-ca.mts",
"proxy:run": "node scripts/run-node.mjs proxy run",
"proxy:start": "node scripts/run-node.mjs proxy start",
"qa:e2e": "node --import tsx scripts/qa-e2e.ts",
"qa:telegram-desktop-recorder": "node --import tsx scripts/e2e/telegram-desktop-recorder.ts",
"qa:e2e": "node --import ./scripts/tsx.mjs scripts/qa-e2e.ts",
"qa:telegram-desktop-recorder": "node --import ./scripts/tsx.mjs scripts/e2e/telegram-desktop-recorder.ts",
"qa:lab:build": "vite build --config extensions/qa-lab/web/vite.config.ts",
"qa:lab:ui": "pnpm openclaw qa ui",
"qa:lab:up": "node --import tsx scripts/qa-lab-up.ts",
"qa:lab:up:fast": "node --import tsx scripts/qa-lab-up.ts --use-prebuilt-image --bind-ui-dist --skip-ui-build",
"qa:lab:up": "node --import ./scripts/tsx.mjs scripts/qa-lab-up.ts",
"qa:lab:up:fast": "node --import ./scripts/tsx.mjs scripts/qa-lab-up.ts --use-prebuilt-image --bind-ui-dist --skip-ui-build",
"qa:lab:watch": "vite build --watch --config extensions/qa-lab/web/vite.config.ts",
"qa:observability:collector-smoke": "pnpm qa:otel:collector-smoke && pnpm qa:prometheus:smoke",
"qa:observability:smoke": "pnpm qa:otel:smoke && pnpm qa:prometheus:smoke",
"qa:otel:collector-smoke": "node --import tsx test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts --collector docker",
"qa:otel:smoke": "node --import tsx test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts",
"qa:code-mode-models": "node --import tsx scripts/code-mode-model-matrix.ts",
"qa:otel:collector-smoke": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts --collector docker",
"qa:otel:smoke": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/runtime/qa-otel-smoke-runtime.ts",
"qa:code-mode-models": "node --import ./scripts/tsx.mjs scripts/code-mode-model-matrix.ts",
"qa:prometheus:smoke": "node scripts/run-node.mjs qa suite --provider-mode mock-openai --scenario docker-prometheus-smoke --concurrency 1 --fast",
"release-metadata:check": "node --import tsx scripts/check-release-metadata-only.mts",
"release:beta": "node --import tsx scripts/release-candidate-checklist.mts",
"release:beta-smoke": "node --import tsx scripts/release-beta-smoke.ts",
"release:candidate": "node --import tsx scripts/release-candidate-checklist.mts",
"release:check": "pnpm build:package && pnpm release:generated:check && node --import tsx scripts/release-check.ts",
"release-metadata:check": "node --import ./scripts/tsx.mjs scripts/check-release-metadata-only.mts",
"release:beta": "node --import ./scripts/tsx.mjs scripts/release-candidate-checklist.mts",
"release:beta-smoke": "node --import ./scripts/tsx.mjs scripts/release-beta-smoke.ts",
"release:candidate": "node --import ./scripts/tsx.mjs scripts/release-candidate-checklist.mts",
"release:check": "pnpm build:package && pnpm release:generated:check && node --import ./scripts/tsx.mjs scripts/release-check.ts",
"release:fast-pretag-check": "bash scripts/release-fast-pretag-check.sh",
"release:generated:check": "node scripts/release-preflight.mjs --check",
"release:openclaw:npm:check": "node --import tsx scripts/openclaw-npm-release-check.ts",
"release:openclaw:npm:verify-published": "node --import tsx scripts/openclaw-npm-postpublish-verify.ts",
"release:prepare": "node --import tsx scripts/release-prepare.ts",
"release:plugins:clawhub:check": "node --import tsx scripts/plugin-clawhub-release-check.ts",
"release:plugins:clawhub:plan": "node --import tsx scripts/plugin-clawhub-release-plan.ts",
"release:plugins:npm:check": "node --import tsx scripts/plugin-npm-release-check.ts",
"release:plugins:npm:plan": "node --import tsx scripts/plugin-npm-release-plan.ts",
"release:verify-beta": "node --import tsx scripts/release-verify-beta.ts",
"release:openclaw:npm:check": "node --import ./scripts/tsx.mjs scripts/openclaw-npm-release-check.ts",
"release:openclaw:npm:verify-published": "node --import ./scripts/tsx.mjs scripts/openclaw-npm-postpublish-verify.ts",
"release:prepare": "node --import ./scripts/tsx.mjs scripts/release-prepare.ts",
"release:plugins:clawhub:check": "node --import ./scripts/tsx.mjs scripts/plugin-clawhub-release-check.ts",
"release:plugins:clawhub:plan": "node --import ./scripts/tsx.mjs scripts/plugin-clawhub-release-plan.ts",
"release:plugins:npm:check": "node --import ./scripts/tsx.mjs scripts/plugin-npm-release-check.ts",
"release:plugins:npm:plan": "node --import ./scripts/tsx.mjs scripts/plugin-npm-release-plan.ts",
"release:verify-beta": "node --import ./scripts/tsx.mjs scripts/release-verify-beta.ts",
"release:prep": "node scripts/release-preflight.mjs --fix",
"release:prep:version": "node scripts/release-preflight.mjs --fix --scope version",
"release:version": "node --import tsx scripts/release-version.ts",
"runtime-sidecars:check": "node --import tsx scripts/generate-runtime-sidecar-paths-baseline.ts --check",
"runtime-sidecars:gen": "node --import tsx scripts/generate-runtime-sidecar-paths-baseline.ts --write",
"sqlite:sessions-schema:check": "node --import tsx scripts/generate-sqlite-session-schema-baseline.ts --check",
"sqlite:sessions-schema:gen": "node --import tsx scripts/generate-sqlite-session-schema-baseline.ts --write",
"release:version": "node --import ./scripts/tsx.mjs scripts/release-version.ts",
"runtime-sidecars:check": "node --import ./scripts/tsx.mjs scripts/generate-runtime-sidecar-paths-baseline.ts --check",
"runtime-sidecars:gen": "node --import ./scripts/tsx.mjs scripts/generate-runtime-sidecar-paths-baseline.ts --write",
"sqlite:sessions-schema:check": "node --import ./scripts/tsx.mjs scripts/generate-sqlite-session-schema-baseline.ts --check",
"sqlite:sessions-schema:gen": "node --import ./scripts/tsx.mjs scripts/generate-sqlite-session-schema-baseline.ts --write",
"start": "node openclaw.mjs",
"test": "node --import tsx scripts/test-projects.mts",
"test": "node --import ./scripts/tsx.mjs scripts/test-projects.mts",
"test:all": "pnpm lint && pnpm build && pnpm test && pnpm test:e2e && pnpm test:live && pnpm test:docker:all",
"test:auth:compat": "node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts src/gateway/server.auth.compat-baseline.test.ts src/gateway/client.test.ts src/gateway/reconnect-gating.test.ts && node scripts/run-vitest.mjs run packages/gateway-protocol/src/connect-error-details.test.ts",
"test:build:singleton": "node --import tsx scripts/test-built-plugin-singleton.mts",
"test:build:status-message-runtime": "node --import tsx scripts/test-built-status-message-runtime.mts",
"test:build:singleton": "node --import ./scripts/tsx.mjs scripts/test-built-plugin-singleton.mts",
"test:build:status-message-runtime": "node --import ./scripts/tsx.mjs scripts/test-built-status-message-runtime.mts",
"test:bundled": "node scripts/run-vitest.mjs run --config test/vitest/vitest.bundled.config.ts",
"test:changed": "node --import tsx scripts/test-projects.mts --changed origin/main",
"test:changed:max": "node --import tsx scripts/test-projects-max.mts --changed origin/main",
"test:changed": "node --import ./scripts/tsx.mjs scripts/test-projects.mts --changed origin/main",
"test:changed:max": "node --import ./scripts/tsx.mjs scripts/test-projects-max.mts --changed origin/main",
"test:channels": "node scripts/run-vitest.mjs run --config test/vitest/vitest.channels.config.ts",
"test:contracts": "pnpm test:contracts:channels && pnpm test:contracts:plugins",
"test:contracts:channels": "node --import tsx scripts/test-projects.mts --maxWorkers=1 test/vitest/vitest.contracts-channel-surface.config.ts test/vitest/vitest.contracts-channel-config.config.ts test/vitest/vitest.contracts-channel-registry.config.ts test/vitest/vitest.contracts-channel-session.config.ts",
"test:contracts:channels": "node --import ./scripts/tsx.mjs scripts/test-projects.mts --maxWorkers=1 test/vitest/vitest.contracts-channel-surface.config.ts test/vitest/vitest.contracts-channel-config.config.ts test/vitest/vitest.contracts-channel-registry.config.ts test/vitest/vitest.contracts-channel-session.config.ts",
"test:contracts:plugins": "node scripts/run-vitest.mjs run --config test/vitest/vitest.contracts-plugin.config.ts --maxWorkers=1",
"test:coverage": "node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts --coverage",
"test:coverage:changed": "node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts --coverage --changed origin/main",
@@ -1856,8 +1856,8 @@
"test:docker:live-models": "bash scripts/test-live-models-docker.sh",
"test:docker:live-models:claude": "OPENCLAW_LIVE_PROVIDERS=claude-cli OPENCLAW_LIVE_MODELS=claude-cli/claude-sonnet-4-6 bash scripts/test-live-models-docker.sh",
"test:docker:live-models:gemini": "OPENCLAW_LIVE_PROVIDERS=google-gemini-cli OPENCLAW_LIVE_MODELS=google-gemini-cli/gemini-3.1-pro-preview bash scripts/test-live-models-docker.sh",
"test:docker:live:all": "node --import tsx scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LIVE_MODE=only -- node scripts/test-docker-all.mjs",
"test:docker:local:all": "node --import tsx scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LIVE_MODE=skip -- node scripts/test-docker-all.mjs",
"test:docker:live:all": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LIVE_MODE=only -- node scripts/test-docker-all.mjs",
"test:docker:local:all": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LIVE_MODE=skip -- node scripts/test-docker-all.mjs",
"test:docker:cli-installer-distribution": "bash scripts/e2e/cli-installer-distribution-docker.sh",
"test:docker:mcp-channels": "bash scripts/e2e/mcp-channels-docker.sh",
"test:docker:mcp-code-mode-gateway": "bash scripts/e2e/mcp-code-mode-gateway-docker.sh",
@@ -1882,109 +1882,109 @@
"test:docker:plugin-lifecycle-matrix": "bash scripts/e2e/plugin-lifecycle-matrix-docker.sh",
"test:docker:plugin-update": "bash scripts/e2e/plugin-update-unchanged-docker.sh",
"test:docker:plugins": "bash scripts/e2e/plugins-docker.sh",
"test:docker:published-upgrade-survivor": "node --import tsx scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LANES=published-upgrade-survivor -- node scripts/test-docker-all.mjs",
"test:docker:published-upgrade-survivor": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_DOCKER_ALL_LANES=published-upgrade-survivor -- node scripts/test-docker-all.mjs",
"test:docker:qr": "bash scripts/e2e/qr-import-docker.sh",
"test:docker:rerun": "node --import tsx scripts/docker-e2e-rerun.mts",
"test:docker:rerun": "node --import ./scripts/tsx.mjs scripts/docker-e2e-rerun.mts",
"test:docker:root-managed-vps-upgrade": "env OPENCLAW_UPGRADE_SURVIVOR_PUBLISHED_BASELINE=1 OPENCLAW_UPGRADE_SURVIVOR_ROOT_MANAGED_VPS=1 OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC=${OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC:-openclaw@2026.5.7} OPENCLAW_UPGRADE_SURVIVOR_DOCKER_RUN_TIMEOUT=${OPENCLAW_UPGRADE_SURVIVOR_DOCKER_RUN_TIMEOUT:-1500s} bash scripts/e2e/upgrade-survivor-docker.sh",
"test:docker:selected-plugins": "bash scripts/e2e/docker-selected-plugins.sh",
"test:docker:session-runtime-context": "bash scripts/e2e/session-runtime-context-docker.sh",
"test:docker:skill-install": "bash scripts/e2e/skill-install-docker.sh",
"test:docker:timings": "node --import tsx scripts/docker-e2e-timings.mts",
"test:docker:timings": "node --import ./scripts/tsx.mjs scripts/docker-e2e-timings.mts",
"test:docker:update-channel-switch": "bash scripts/e2e/update-channel-switch-docker.sh",
"test:docker:update-corrupt-plugin": "bash scripts/e2e/update-corrupt-plugin-docker.sh",
"test:docker:update-migration": "env OPENCLAW_UPGRADE_SURVIVOR_PUBLISHED_BASELINE=1 OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC=${OPENCLAW_UPGRADE_SURVIVOR_BASELINE_SPEC:-openclaw@2026.4.23} OPENCLAW_UPGRADE_SURVIVOR_SCENARIO=${OPENCLAW_UPGRADE_SURVIVOR_SCENARIO:-plugin-deps-cleanup} bash scripts/e2e/upgrade-survivor-docker.sh",
"test:docker:update-restart-auth": "env OPENCLAW_UPGRADE_SURVIVOR_UPDATE_RESTART_MODE=auto-auth OPENCLAW_UPGRADE_SURVIVOR_DOCKER_RUN_TIMEOUT=${OPENCLAW_UPGRADE_SURVIVOR_DOCKER_RUN_TIMEOUT:-1500s} bash scripts/e2e/upgrade-survivor-docker.sh",
"test:docker:update-run-package-self-upgrade": "bash scripts/e2e/update-run-package-self-upgrade-docker.sh",
"test:docker:upgrade-survivor": "bash scripts/e2e/upgrade-survivor-docker.sh",
"test:env-mutations:report": "node --import tsx scripts/test-env-mutation-report.ts",
"test:skip-inventory:report": "node --import tsx scripts/test-skip-inventory.ts",
"test:type-suppression-inventory:report": "node --import tsx scripts/type-suppression-inventory.ts",
"test:env-mutations:report": "node --import ./scripts/tsx.mjs scripts/test-env-mutation-report.ts",
"test:skip-inventory:report": "node --import ./scripts/tsx.mjs scripts/test-skip-inventory.ts",
"test:type-suppression-inventory:report": "node --import ./scripts/tsx.mjs scripts/type-suppression-inventory.ts",
"test:e2e": "pnpm test:e2e:gateway && pnpm test:e2e:agent-plugin-gateway && pnpm test:ui:e2e",
"test:e2e:agent-plugin-gateway": "node --import tsx scripts/agent-plugin-gateway-e2e.ts",
"test:e2e:browser-extension": "node --import tsx scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers -- node --import tsx scripts/ensure-playwright-chromium.mts --require-playwright-chromium && node --import tsx scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers OPENCLAW_BROWSER_EXTENSION_E2E=1 OPENCLAW_E2E_WORKERS=1 -- node scripts/run-vitest.mjs extensions/browser/chrome-extension/bootstrap.chromium.test.ts",
"test:e2e:agent-plugin-gateway": "node --import ./scripts/tsx.mjs scripts/agent-plugin-gateway-e2e.ts",
"test:e2e:browser-extension": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers -- node --import ./scripts/tsx.mjs scripts/ensure-playwright-chromium.mts --require-playwright-chromium && node --import ./scripts/tsx.mjs scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers OPENCLAW_BROWSER_EXTENSION_E2E=1 OPENCLAW_E2E_WORKERS=1 -- node scripts/run-vitest.mjs extensions/browser/chrome-extension/bootstrap.chromium.test.ts",
"test:e2e:gateway": "node scripts/run-vitest.mjs run --config test/vitest/vitest.e2e.config.ts",
"test:e2e:openshell": "node --import tsx scripts/run-with-env.mts OPENCLAW_E2E_OPENSHELL=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.e2e.config.ts extensions/openshell/src/backend.e2e.test.ts",
"test:e2e:openshell": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_E2E_OPENSHELL=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.e2e.config.ts extensions/openshell/src/backend.e2e.test.ts",
"test:e2e:status-corrupt-plugin-deps": "bash scripts/e2e/status-corrupt-plugin-deps.sh",
"test:extension": "node --import tsx scripts/test-extension.mts",
"test:extensions": "node --import tsx scripts/test-projects.mts extensions",
"test:extensions:batch": "node --import tsx scripts/test-extension-batch.mts",
"test:extensions:memory": "node --import tsx scripts/profile-extension-memory.mts",
"test:extensions:package-boundary": "node --import tsx scripts/check-extension-package-tsc-boundary.mts",
"test:extensions:package-boundary:canary": "node --import tsx scripts/check-extension-package-tsc-boundary.mts --mode=canary",
"test:extensions:package-boundary:compile": "node --import tsx scripts/check-extension-package-tsc-boundary.mts --mode=compile",
"test:extension": "node --import ./scripts/tsx.mjs scripts/test-extension.mts",
"test:extensions": "node --import ./scripts/tsx.mjs scripts/test-projects.mts extensions",
"test:extensions:batch": "node --import ./scripts/tsx.mjs scripts/test-extension-batch.mts",
"test:extensions:memory": "node --import ./scripts/tsx.mjs scripts/profile-extension-memory.mts",
"test:extensions:package-boundary": "node --import ./scripts/tsx.mjs scripts/check-extension-package-tsc-boundary.mts",
"test:extensions:package-boundary:canary": "node --import ./scripts/tsx.mjs scripts/check-extension-package-tsc-boundary.mts --mode=canary",
"test:extensions:package-boundary:compile": "node --import ./scripts/tsx.mjs scripts/check-extension-package-tsc-boundary.mts --mode=compile",
"test:fast": "node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts",
"test:force": "node --import tsx scripts/test-force.ts",
"test:gateway": "node --import tsx scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts",
"test:gateway:cpu-scenarios": "node --import tsx scripts/check-gateway-cpu-scenarios.mts",
"test:force": "node --import ./scripts/tsx.mjs scripts/test-force.ts",
"test:gateway": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts",
"test:gateway:cpu-scenarios": "node --import ./scripts/tsx.mjs scripts/check-gateway-cpu-scenarios.mts",
"test:gateway:concurrency": "node scripts/bench-gateway-concurrency.ts",
"test:gateway:memory-fd-repro": "node --import tsx scripts/check-memory-fd-repro.mts",
"test:gateway:watch-regression": "node --import tsx scripts/check-gateway-watch-regression.mts",
"test:gateway:memory-fd-repro": "node --import ./scripts/tsx.mjs scripts/check-memory-fd-repro.mts",
"test:gateway:watch-regression": "node --import ./scripts/tsx.mjs scripts/check-gateway-watch-regression.mts",
"test:install:e2e": "bash scripts/test-install-sh-e2e-docker.sh",
"test:install:e2e:anthropic": "OPENCLAW_E2E_MODELS=anthropic bash scripts/test-install-sh-e2e-docker.sh",
"test:install:e2e:openai": "OPENCLAW_E2E_MODELS=openai bash scripts/test-install-sh-e2e-docker.sh",
"test:install:smoke": "bash scripts/test-install-sh-docker.sh",
"test:live": "node --import tsx scripts/test-live.mts",
"test:live:cache": "node --import tsx scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 -- node --import tsx scripts/check-live-cache.ts",
"test:live:codex-harness": "node --import tsx scripts/test-live.mts --codex-harness -- src/gateway/gateway-codex-harness.live.test.ts",
"test:live:system-agent-rescue-channel": "node --import tsx scripts/run-with-env.mts OPENCLAW_LIVE_SYSTEM_AGENT_RESCUE_CHANNEL=1 -- node --import tsx scripts/test-live.mts -- src/system-agent/rescue-channel.live.test.ts",
"test:live:gateway-profiles": "node --import tsx scripts/test-live.mts -- src/gateway/gateway-models.profiles.live.test.ts",
"test:live:media": "node --import tsx test/e2e/qa-lab/media/hosted-media-provider-live.ts",
"test:live:media:image": "node --import tsx test/e2e/qa-lab/media/hosted-media-provider-live.ts image",
"test:live:media:music": "node --import tsx test/e2e/qa-lab/media/hosted-media-provider-live.ts music",
"test:live:media:video": "node --import tsx test/e2e/qa-lab/media/hosted-media-provider-live.ts video",
"test:live:models-profiles": "node --import tsx scripts/test-live.mts -- src/agents/models.profiles.live.test.ts",
"test:macos:ci": "node --import tsx scripts/test-projects.mts src/daemon/launchd.test.ts src/daemon/runtime-paths.test.ts src/daemon/runtime-binary.test.ts src/gateway/worker-environments/workspace-rsync-path.test.ts src/infra/brew.test.ts src/infra/stable-node-path.test.ts src/process/supervisor/adapters/child.service-lifecycle.test.ts test/scripts/vitest-process-group.test.ts test/scripts/package-mac-app.test.ts test/scripts/package-mac-dist.test.ts test/scripts/create-dmg.test.ts test/scripts/codesign-mac-app.test.ts test/scripts/notarize-mac-artifact.test.ts test/scripts/mac-elevation-host.test.ts",
"test:max": "node --import tsx scripts/test-projects-max.mts",
"test:live": "node --import ./scripts/tsx.mjs scripts/test-live.mts",
"test:live:cache": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 -- node --import ./scripts/tsx.mjs scripts/check-live-cache.ts",
"test:live:codex-harness": "node --import ./scripts/tsx.mjs scripts/test-live.mts --codex-harness -- src/gateway/gateway-codex-harness.live.test.ts",
"test:live:system-agent-rescue-channel": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_LIVE_SYSTEM_AGENT_RESCUE_CHANNEL=1 -- node --import ./scripts/tsx.mjs scripts/test-live.mts -- src/system-agent/rescue-channel.live.test.ts",
"test:live:gateway-profiles": "node --import ./scripts/tsx.mjs scripts/test-live.mts -- src/gateway/gateway-models.profiles.live.test.ts",
"test:live:media": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/media/hosted-media-provider-live.ts",
"test:live:media:image": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/media/hosted-media-provider-live.ts image",
"test:live:media:music": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/media/hosted-media-provider-live.ts music",
"test:live:media:video": "node --import ./scripts/tsx.mjs test/e2e/qa-lab/media/hosted-media-provider-live.ts video",
"test:live:models-profiles": "node --import ./scripts/tsx.mjs scripts/test-live.mts -- src/agents/models.profiles.live.test.ts",
"test:macos:ci": "node --import ./scripts/tsx.mjs scripts/test-projects.mts src/daemon/launchd.test.ts src/daemon/runtime-paths.test.ts src/daemon/runtime-binary.test.ts src/gateway/worker-environments/workspace-rsync-path.test.ts src/infra/brew.test.ts src/infra/stable-node-path.test.ts src/process/supervisor/adapters/child.service-lifecycle.test.ts test/scripts/vitest-process-group.test.ts test/scripts/package-mac-app.test.ts test/scripts/package-mac-dist.test.ts test/scripts/create-dmg.test.ts test/scripts/codesign-mac-app.test.ts test/scripts/notarize-mac-artifact.test.ts test/scripts/mac-elevation-host.test.ts",
"test:max": "node --import ./scripts/tsx.mjs scripts/test-projects-max.mts",
"test:parallels:linux": "bash scripts/e2e/parallels-linux-smoke.sh",
"test:parallels:macos": "bash scripts/e2e/parallels-macos-smoke.sh",
"test:parallels:npm-update": "bash scripts/e2e/parallels-npm-update-smoke.sh",
"test:parallels:windows:prepare": "bash scripts/e2e/parallels-windows-prepare.sh",
"test:parallels:windows": "bash scripts/e2e/parallels-windows-smoke.sh",
"test:agents:concurrency": "node --import tsx scripts/bench-agent-concurrency.ts",
"test:tasks:sqlite-churn": "node --import tsx scripts/bench-task-registry-sqlite.ts",
"test:perf:budget": "node --import tsx scripts/test-perf-budget.mts",
"test:perf:changed:bench": "node --import tsx scripts/bench-test-changed.mts",
"test:perf:groups": "node --import tsx scripts/test-group-report.mts",
"test:perf:groups:compare": "node --import tsx scripts/test-group-report.mts --compare",
"test:perf:hotspots": "node --import tsx scripts/test-hotspots.mts",
"test:perf:imports": "node --import tsx scripts/test-projects-imports.mts",
"test:perf:imports:changed": "node --import tsx scripts/test-projects-imports.mts --changed origin/main",
"test:perf:profile:main": "node --import tsx scripts/run-vitest-profile.mts main",
"test:perf:profile:runner": "node --import tsx scripts/run-vitest-profile.mts runner",
"test:sqlite:perf": "node --import tsx scripts/bench-sqlite-state.ts --profile default --output .artifacts/sqlite-perf/default.json",
"test:sqlite:perf:large": "node --import tsx scripts/bench-sqlite-state.ts --profile large --output .artifacts/sqlite-perf/large.json",
"test:sqlite:perf:smoke": "node --import tsx scripts/bench-sqlite-state.ts --profile smoke --output .artifacts/sqlite-perf/smoke.json",
"test:plugins:gateway-gauntlet": "node --import tsx scripts/check-plugin-gateway-gauntlet.mts",
"test:plugins:init-provider-scaffold": "node --import tsx scripts/validate-plugin-init-provider-scaffold.ts",
"test:agents:concurrency": "node --import ./scripts/tsx.mjs scripts/bench-agent-concurrency.ts",
"test:tasks:sqlite-churn": "node --import ./scripts/tsx.mjs scripts/bench-task-registry-sqlite.ts",
"test:perf:budget": "node --import ./scripts/tsx.mjs scripts/test-perf-budget.mts",
"test:perf:changed:bench": "node --import ./scripts/tsx.mjs scripts/bench-test-changed.mts",
"test:perf:groups": "node --import ./scripts/tsx.mjs scripts/test-group-report.mts",
"test:perf:groups:compare": "node --import ./scripts/tsx.mjs scripts/test-group-report.mts --compare",
"test:perf:hotspots": "node --import ./scripts/tsx.mjs scripts/test-hotspots.mts",
"test:perf:imports": "node --import ./scripts/tsx.mjs scripts/test-projects-imports.mts",
"test:perf:imports:changed": "node --import ./scripts/tsx.mjs scripts/test-projects-imports.mts --changed origin/main",
"test:perf:profile:main": "node --import ./scripts/tsx.mjs scripts/run-vitest-profile.mts main",
"test:perf:profile:runner": "node --import ./scripts/tsx.mjs scripts/run-vitest-profile.mts runner",
"test:sqlite:perf": "node --import ./scripts/tsx.mjs scripts/bench-sqlite-state.ts --profile default --output .artifacts/sqlite-perf/default.json",
"test:sqlite:perf:large": "node --import ./scripts/tsx.mjs scripts/bench-sqlite-state.ts --profile large --output .artifacts/sqlite-perf/large.json",
"test:sqlite:perf:smoke": "node --import ./scripts/tsx.mjs scripts/bench-sqlite-state.ts --profile smoke --output .artifacts/sqlite-perf/smoke.json",
"test:plugins:gateway-gauntlet": "node --import ./scripts/tsx.mjs scripts/check-plugin-gateway-gauntlet.mts",
"test:plugins:init-provider-scaffold": "node --import ./scripts/tsx.mjs scripts/validate-plugin-init-provider-scaffold.ts",
"test:plugins:kitchen-sink-live": "bash -lc 'if [ -x \"$HOME/.local/bin/openclaw-testbox-env\" ]; then exec \"$HOME/.local/bin/openclaw-testbox-env\" pnpm openclaw qa suite --provider-mode live-frontier --scenario kitchen-sink-live-openai; fi; exec pnpm openclaw qa suite --provider-mode live-frontier --scenario kitchen-sink-live-openai'",
"test:plugins:kitchen-sink-rpc": "node --import tsx scripts/e2e/kitchen-sink-rpc-walk.mts",
"test:sectriage": "node --import tsx scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts && node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts --exclude src/process/exec.test.ts",
"test:serial": "node --import tsx scripts/test-projects-serial.mts",
"test:stability:gateway": "node --import tsx scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts src/gateway/gateway-stability.test.ts && node --import tsx scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.logging.config.ts src/logging/diagnostic-stability-bundle.test.ts && node --import tsx scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.infra.config.ts src/infra/fatal-error-hooks.test.ts",
"test:cli-response:contract": "node --import tsx scripts/build-all.mts cliStartup && node --import tsx scripts/test-cli-startup-bench-budget.mts --preset response --runs 1 --warmup 0 --timeout-ms 10000 --skip-baseline",
"test:startup:bench": "node --import tsx scripts/bench-cli-startup.ts",
"test:startup:bench:check": "node --import tsx scripts/test-cli-startup-bench-budget.mts",
"test:startup:bench:save": "node --import tsx scripts/bench-cli-startup.ts --preset all --runs 5 --warmup 1 --output .artifacts/cli-startup-bench-all.json",
"test:startup:bench:smoke": "node --import tsx scripts/ensure-cli-startup-build.mts && node --import tsx scripts/bench-cli-startup.ts --preset real --case gatewayStatusJson --runs 1 --warmup 0 --output .artifacts/cli-startup-bench-smoke.json",
"test:startup:bench:update": "node --import tsx scripts/test-update-cli-startup-bench.mts",
"test:startup:gateway": "node --import tsx scripts/bench-gateway-startup.ts",
"test:restart:gateway": "node --import tsx scripts/bench-gateway-restart.ts",
"test:sessions:hydration-memory": "node --import tsx scripts/bench-session-manager-hydration-memory.ts",
"test:startup:memory": "node --import tsx scripts/ensure-cli-startup-build.mts && node scripts/check-cli-startup-memory.mjs",
"test:ui": "pnpm lint:ui:no-raw-window-open && node --import tsx scripts/ensure-playwright-chromium.mts && pnpm --dir ui test",
"test:ui:e2e": "node --import tsx scripts/ensure-playwright-chromium.mts && node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner",
"test:plugins:kitchen-sink-rpc": "node --import ./scripts/tsx.mjs scripts/e2e/kitchen-sink-rpc-walk.mts",
"test:sectriage": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts && node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts --exclude src/process/exec.test.ts",
"test:serial": "node --import ./scripts/tsx.mjs scripts/test-projects-serial.mts",
"test:stability:gateway": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts src/gateway/gateway-stability.test.ts && node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.logging.config.ts src/logging/diagnostic-stability-bundle.test.ts && node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.infra.config.ts src/infra/fatal-error-hooks.test.ts",
"test:cli-response:contract": "node --import ./scripts/tsx.mjs scripts/build-all.mts cliStartup && node --import ./scripts/tsx.mjs scripts/test-cli-startup-bench-budget.mts --preset response --runs 1 --warmup 0 --timeout-ms 10000 --skip-baseline",
"test:startup:bench": "node --import ./scripts/tsx.mjs scripts/bench-cli-startup.ts",
"test:startup:bench:check": "node --import ./scripts/tsx.mjs scripts/test-cli-startup-bench-budget.mts",
"test:startup:bench:save": "node --import ./scripts/tsx.mjs scripts/bench-cli-startup.ts --preset all --runs 5 --warmup 1 --output .artifacts/cli-startup-bench-all.json",
"test:startup:bench:smoke": "node --import ./scripts/tsx.mjs scripts/ensure-cli-startup-build.mts && node --import ./scripts/tsx.mjs scripts/bench-cli-startup.ts --preset real --case gatewayStatusJson --runs 1 --warmup 0 --output .artifacts/cli-startup-bench-smoke.json",
"test:startup:bench:update": "node --import ./scripts/tsx.mjs scripts/test-update-cli-startup-bench.mts",
"test:startup:gateway": "node --import ./scripts/tsx.mjs scripts/bench-gateway-startup.ts",
"test:restart:gateway": "node --import ./scripts/tsx.mjs scripts/bench-gateway-restart.ts",
"test:sessions:hydration-memory": "node --import ./scripts/tsx.mjs scripts/bench-session-manager-hydration-memory.ts",
"test:startup:memory": "node --import ./scripts/tsx.mjs scripts/ensure-cli-startup-build.mts && node scripts/check-cli-startup-memory.mjs",
"test:ui": "pnpm lint:ui:no-raw-window-open && node --import ./scripts/tsx.mjs scripts/ensure-playwright-chromium.mts && pnpm --dir ui test",
"test:ui:e2e": "node --import ./scripts/tsx.mjs scripts/ensure-playwright-chromium.mts && node scripts/run-vitest.mjs run --config test/vitest/vitest.ui-e2e.config.ts --configLoader runner",
"test:unit": "pnpm test:unit:fast && node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts",
"test:unit:fast": "node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts",
"test:unit:fast:audit": "node --import tsx scripts/test-unit-fast-audit.mts",
"test:voicecall:closedloop": "node --import tsx scripts/test-voicecall-closedloop.mts",
"test:watch": "node --import tsx scripts/test-projects.mts --watch",
"test:unit:fast:audit": "node --import ./scripts/tsx.mjs scripts/test-unit-fast-audit.mts",
"test:voicecall:closedloop": "node --import ./scripts/tsx.mjs scripts/test-voicecall-closedloop.mts",
"test:watch": "node --import ./scripts/tsx.mjs scripts/test-projects.mts --watch",
"test:windows:ci": "pnpm test:windows:ci:1 && pnpm test:windows:ci:2",
"test:windows:ci:1": "node --import tsx scripts/test-projects.mts src/state/openclaw-state-ownership.test.ts src/snapshot/local-repository.windows.test.ts src/state/openclaw-database-paths.windows.test.ts src/node-host/invoke-system-run-allowlist.test.ts src/node-host/node-worker-transfer-client.test.ts packages/terminal-core/src/display-string.test.ts src/config/sessions/session-accessor.sqlite-archive.worker.test.ts src/commands/doctor-gateway-auth-token.windows.test.ts src/infra/state-migrations.audit-logs.windows.test.ts src/commands/backup-verify.test.ts src/commands/agents.commands.list.test.ts src/shared/runtime-import.test.ts src/shared/worker-bundle-archive.test.ts src/node-host/node-worker-bundle-installer.test.ts test/scripts/direct-run-entrypoints.test.ts test/scripts/format-generated-module.test.ts test/scripts/openclaw-cross-os-installer.windows.test.ts test/scripts/openclaw-cross-os-release-workflow.test.ts test/scripts/pnpm-runner.test.ts test/scripts/run-with-env.test.ts test/scripts/ui.test.ts test/scripts/vitest-process-group.test.ts src/agents/tools/media-tool-file-url.windows.test.ts extensions/memory-core/src/memory-extra-file-path.windows.test.ts src/daemon/schtasks.startup-fallback.test.ts src/plugin-sdk/node-host.test.ts test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts extensions/lobster/src/lobster-runner.test.ts src/gateway/worker-environments/workspace-quiescence.windows.test.ts",
"test:windows:ci:2": "node --import tsx scripts/test-projects.mts src/infra/sqlite-snapshot.test.ts src/infra/ports.test.ts src/infra/advertised-lan-host.windows.test.ts src/infra/update-managed-service-handoff-command.test.ts src/infra/update-managed-service-handoff-lifecycle.test.ts src/infra/executable-path.test.ts src/infra/fs-safe-remove.test.ts src/infra/state-migrations.legacy-session-store.test.ts src/infra/windows-install-roots.test.ts src/infra/ssh-client.windows.test.ts src/infra/exec-allowlist-pattern.test.ts src/infra/process-env.test.ts src/agents/sessions/windows-git-bash-path.test.ts test/scripts/npm-runner.test.ts test/scripts/ts-topology.test.ts src/test-utils/openclaw-test-state.test.ts src/utils.test.ts src/media/local-media-path.windows.test.ts src/media/web-media.file-url.windows.test.ts src/process/exec.windows.test.ts src/process/exec.windows.integration.test.ts src/agents/sessions/exec.real.test.ts src/process/windows-command.test.ts src/process/terminal-pty.test.ts src/process/supervisor/supervisor.anchored-shell.real.test.ts src/tui/tui.resolve-codex-bin.test.ts src/media-understanding/attachments.file-url.windows.test.ts src/cli/daemon-cli/status.print.test.ts src/cli/mcp-cli.path-case.windows.test.ts src/auto-reply/usage-bar/template.windows.test.ts src/auto-reply/reply.triggers.trigger-handling.stages-inbound-media-into-sandbox-workspace.test.ts src/agents/provider-local-service.env-case.test.ts src/agents/bash-tools.exec.script-preflight.test.ts src/agents/agent-tools.read.windows.test.ts src/agents/agent-tools.read.host-operations.test.ts src/agents/sandbox/fs-paths.test.ts src/agents/sessions/tools/render-utils.test.ts src/agents/sessions/tools/path-utils.test.ts extensions/msteams/src/media-helpers.test.ts extensions/msteams/src/messenger.test.ts extensions/mxc/test/mxc-backend.test.ts extensions/mxc/test/sandbox-policy-loader.test.ts",
"test:windows:schtasks:integration": "node --import tsx scripts/run-with-env.mts CI_WINDOWS_SCHTASKS_INTEGRATION=1 OPENCLAW_E2E_SKIP_BUILD=1 OPENCLAW_E2E_VERBOSE=1 OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs src/daemon/schtasks.integration.e2e.test.ts",
"tool-display:check": "node --import tsx scripts/tool-display.ts --check",
"tool-display:write": "node --import tsx scripts/tool-display.ts --write",
"ts-topology": "node --import tsx scripts/ts-topology.ts",
"test:windows:ci:1": "node --import ./scripts/tsx.mjs scripts/test-projects.mts src/state/openclaw-state-ownership.test.ts src/snapshot/local-repository.windows.test.ts src/state/openclaw-database-paths.windows.test.ts src/node-host/invoke-system-run-allowlist.test.ts src/node-host/node-worker-transfer-client.test.ts packages/terminal-core/src/display-string.test.ts src/config/sessions/session-accessor.sqlite-archive.worker.test.ts src/commands/doctor-gateway-auth-token.windows.test.ts src/infra/state-migrations.audit-logs.windows.test.ts src/commands/backup-verify.test.ts src/commands/agents.commands.list.test.ts src/shared/runtime-import.test.ts src/shared/worker-bundle-archive.test.ts src/node-host/node-worker-bundle-installer.test.ts test/scripts/direct-run-entrypoints.test.ts test/scripts/format-generated-module.test.ts test/scripts/openclaw-cross-os-installer.windows.test.ts test/scripts/openclaw-cross-os-release-workflow.test.ts test/scripts/pnpm-runner.test.ts test/scripts/run-with-env.test.ts test/scripts/ui.test.ts test/scripts/vitest-process-group.test.ts src/agents/tools/media-tool-file-url.windows.test.ts extensions/memory-core/src/memory-extra-file-path.windows.test.ts src/daemon/schtasks.startup-fallback.test.ts src/plugin-sdk/node-host.test.ts test/e2e/qa-lab/runtime/package-openclaw-for-docker.e2e.test.ts extensions/lobster/src/lobster-runner.test.ts src/gateway/worker-environments/workspace-quiescence.windows.test.ts",
"test:windows:ci:2": "node --import ./scripts/tsx.mjs scripts/test-projects.mts src/infra/sqlite-snapshot.test.ts src/infra/ports.test.ts src/infra/advertised-lan-host.windows.test.ts src/infra/update-managed-service-handoff-command.test.ts src/infra/update-managed-service-handoff-lifecycle.test.ts src/infra/executable-path.test.ts src/infra/fs-safe-remove.test.ts src/infra/state-migrations.legacy-session-store.test.ts src/infra/windows-install-roots.test.ts src/infra/ssh-client.windows.test.ts src/infra/exec-allowlist-pattern.test.ts src/infra/process-env.test.ts src/agents/sessions/windows-git-bash-path.test.ts test/scripts/npm-runner.test.ts test/scripts/ts-topology.test.ts src/test-utils/openclaw-test-state.test.ts src/utils.test.ts src/media/local-media-path.windows.test.ts src/media/web-media.file-url.windows.test.ts src/process/exec.windows.test.ts src/process/exec.windows.integration.test.ts src/agents/sessions/exec.real.test.ts src/process/windows-command.test.ts src/process/terminal-pty.test.ts src/process/supervisor/supervisor.anchored-shell.real.test.ts src/tui/tui.resolve-codex-bin.test.ts src/media-understanding/attachments.file-url.windows.test.ts src/cli/daemon-cli/status.print.test.ts src/cli/mcp-cli.path-case.windows.test.ts src/auto-reply/usage-bar/template.windows.test.ts src/auto-reply/reply.triggers.trigger-handling.stages-inbound-media-into-sandbox-workspace.test.ts src/agents/provider-local-service.env-case.test.ts src/agents/bash-tools.exec.script-preflight.test.ts src/agents/agent-tools.read.windows.test.ts src/agents/agent-tools.read.host-operations.test.ts src/agents/sandbox/fs-paths.test.ts src/agents/sessions/tools/render-utils.test.ts src/agents/sessions/tools/path-utils.test.ts extensions/msteams/src/media-helpers.test.ts extensions/msteams/src/messenger.test.ts extensions/mxc/test/mxc-backend.test.ts extensions/mxc/test/sandbox-policy-loader.test.ts",
"test:windows:schtasks:integration": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts CI_WINDOWS_SCHTASKS_INTEGRATION=1 OPENCLAW_E2E_SKIP_BUILD=1 OPENCLAW_E2E_VERBOSE=1 OPENCLAW_VITEST_MAX_WORKERS=1 -- node scripts/run-vitest.mjs src/daemon/schtasks.integration.e2e.test.ts",
"tool-display:check": "node --import ./scripts/tsx.mjs scripts/tool-display.ts --check",
"tool-display:write": "node --import ./scripts/tsx.mjs scripts/tool-display.ts --write",
"ts-topology": "node --import ./scripts/tsx.mjs scripts/ts-topology.ts",
"tsgo": "pnpm tsgo:core",
"tsgo:all": "pnpm tsgo:core:all && pnpm tsgo:extensions:all && pnpm tsgo:scripts && pnpm tsgo:test:root",
"tsgo:core": "node scripts/run-tsgo.mjs -p tsconfig.core.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/core.tsbuildinfo",
@@ -1994,7 +1994,7 @@
"tsgo:extensions:all": "node scripts/run-tsgo.mjs -b tsconfig.extensions.projects.json",
"tsgo:extensions:test": "node scripts/run-tsgo.mjs -p test/tsconfig/tsconfig.extensions.test.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/extensions-test.tsbuildinfo",
"tsgo:prod": "pnpm tsgo:core && pnpm tsgo:ui && pnpm tsgo:extensions",
"tsgo:profile": "node --import tsx scripts/profile-tsgo.mts",
"tsgo:profile": "node --import ./scripts/tsx.mjs scripts/profile-tsgo.mts",
"tsgo:scripts": "node scripts/run-tsgo.mjs -p tsconfig.scripts.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/scripts.tsbuildinfo",
"tsgo:test": "pnpm tsgo:core:test && pnpm tsgo:extensions:test && pnpm tsgo:test:root",
"tsgo:test:extensions": "pnpm tsgo:extensions:test",
@@ -2004,32 +2004,32 @@
"tsgo:test:ui": "node scripts/run-tsgo-core-test-shards.mjs ui",
"tsgo:ui": "node scripts/run-tsgo.mjs -p tsconfig.ui.json --incremental --tsBuildInfoFile .artifacts/tsgo-cache/ui.tsbuildinfo",
"tui": "node scripts/run-node.mjs tui",
"tui:dev": "node --import tsx scripts/run-with-env.mts OPENCLAW_PROFILE=dev -- node scripts/run-node.mjs --dev tui",
"tui:pty:test:watch": "node --import tsx scripts/dev/tui-pty-test-watch.ts",
"tui:pty:test:watch:all": "node --import tsx scripts/dev/tui-pty-test-watch.ts --mode all",
"tui:pty:test:watch:fake": "node --import tsx scripts/dev/tui-pty-test-watch.ts --mode fake",
"tui:pty:test:watch:local": "node --import tsx scripts/dev/tui-pty-test-watch.ts --mode local",
"ui:boot-manifest:gen": "node --import tsx scripts/control-ui-boot-manifest.mts",
"tui:dev": "node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_PROFILE=dev -- node scripts/run-node.mjs --dev tui",
"tui:pty:test:watch": "node --import ./scripts/tsx.mjs scripts/dev/tui-pty-test-watch.ts",
"tui:pty:test:watch:all": "node --import ./scripts/tsx.mjs scripts/dev/tui-pty-test-watch.ts --mode all",
"tui:pty:test:watch:fake": "node --import ./scripts/tsx.mjs scripts/dev/tui-pty-test-watch.ts --mode fake",
"tui:pty:test:watch:local": "node --import ./scripts/tsx.mjs scripts/dev/tui-pty-test-watch.ts --mode local",
"ui:boot-manifest:gen": "node --import ./scripts/tsx.mjs scripts/control-ui-boot-manifest.mts",
"ui:build": "node scripts/ui.js build",
"ui:dev": "node scripts/ui.js dev",
"ui:i18n:baseline": "node --import tsx scripts/control-ui-i18n-verify.ts baseline",
"ui:i18n:check": "node --import tsx scripts/control-ui-i18n.ts check",
"ui:i18n:report": "node --import tsx scripts/control-ui-i18n-report.ts",
"ui:i18n:sync": "node --import tsx scripts/control-ui-i18n.ts sync --write",
"ui:i18n:verify": "node --import tsx scripts/control-ui-i18n-verify.ts verify",
"ui:proof:composer-mic-hover": "node --import tsx scripts/capture-composer-mic-hover-proof.mts",
"ui:proof:injected-turn-notice": "node --import tsx scripts/capture-injected-turn-notice-proof.mts",
"ui:proof:model-picker": "node --import tsx scripts/capture-model-picker-proof.mts",
"ui:proof:session-toolbar": "node --import tsx scripts/capture-session-toolbar-proof.mts",
"ui:proof:workboard": "node --import tsx scripts/capture-workboard-ui-proof.mts",
"native:i18n:baseline": "node --import tsx scripts/native-app-i18n.ts baseline --write",
"native:i18n:check": "node --import tsx scripts/native-app-i18n.ts check",
"native:i18n:sync": "node --import tsx scripts/native-app-i18n.ts sync --write",
"native:i18n:verify": "node --import tsx scripts/native-app-i18n.ts verify",
"android:i18n:check": "node --import tsx scripts/android-app-i18n.ts check",
"apple:i18n:check": "node --import tsx scripts/apple-app-i18n.ts check",
"ui:i18n:baseline": "node --import ./scripts/tsx.mjs scripts/control-ui-i18n-verify.ts baseline",
"ui:i18n:check": "node --import ./scripts/tsx.mjs scripts/control-ui-i18n.ts check",
"ui:i18n:report": "node --import ./scripts/tsx.mjs scripts/control-ui-i18n-report.ts",
"ui:i18n:sync": "node --import ./scripts/tsx.mjs scripts/control-ui-i18n.ts sync --write",
"ui:i18n:verify": "node --import ./scripts/tsx.mjs scripts/control-ui-i18n-verify.ts verify",
"ui:proof:composer-mic-hover": "node --import ./scripts/tsx.mjs scripts/capture-composer-mic-hover-proof.mts",
"ui:proof:injected-turn-notice": "node --import ./scripts/tsx.mjs scripts/capture-injected-turn-notice-proof.mts",
"ui:proof:model-picker": "node --import ./scripts/tsx.mjs scripts/capture-model-picker-proof.mts",
"ui:proof:session-toolbar": "node --import ./scripts/tsx.mjs scripts/capture-session-toolbar-proof.mts",
"ui:proof:workboard": "node --import ./scripts/tsx.mjs scripts/capture-workboard-ui-proof.mts",
"native:i18n:baseline": "node --import ./scripts/tsx.mjs scripts/native-app-i18n.ts baseline --write",
"native:i18n:check": "node --import ./scripts/tsx.mjs scripts/native-app-i18n.ts check",
"native:i18n:sync": "node --import ./scripts/tsx.mjs scripts/native-app-i18n.ts sync --write",
"native:i18n:verify": "node --import ./scripts/tsx.mjs scripts/native-app-i18n.ts verify",
"android:i18n:check": "node --import ./scripts/tsx.mjs scripts/android-app-i18n.ts check",
"apple:i18n:check": "node --import ./scripts/tsx.mjs scripts/apple-app-i18n.ts check",
"ui:install": "node scripts/ui.js install",
"verify": "node --import tsx scripts/verify.mts"
"verify": "node --import ./scripts/tsx.mjs scripts/verify.mts"
},
"dependencies": {
"@agentclientprotocol/sdk": "1.3.0",
+1 -1
View File
@@ -62,7 +62,7 @@ const WINDOWS_SQLITE_SCOPE_RE = /^src\/(?:state\/|.*sqlite.*\.ts$)/;
const WINDOWS_FILE_URL_SCOPE_RE =
/^(?:src\/agents\/tools\/(?:media-tool-file-url\.windows\.test|media-tool-shared(?:\.test)?|pdf-tool(?:\.test)?)|src\/auto-reply\/(?:reply\/stage-sandbox-media|reply\.triggers\.trigger-handling\.stages-inbound-media-into-sandbox-workspace\.test)|src\/media\/(?:local-media-path(?:\.windows\.test)?|local-roots(?:\.test)?|web-media(?:\.file-url\.windows\.test)?)|src\/channels\/inbound-event\/media(?:\.test)?|src\/gateway\/managed-image-attachments(?:\.test)?|extensions\/msteams\/src\/(?:media-helpers|messenger)(?:\.test)?)\.ts$/;
const WINDOWS_SCOPE_RE =
/^(extensions\/mxc\/|src\/agents\/(?:bash-tools\.exec-script-(?:preflight|target)|bash-tools\.exec\.script-preflight\.test)\.ts$|src\/config\/sessions\/(?:session-accessor\.sqlite-archive(?:\.worker(?:\.test)?)?|store\.session-lifecycle-mutation\.test)\.ts$|src\/process\/|src\/infra\/(?:(?:advertised-lan-host|exec-allowlist-pattern|fs-safe-remove)(?:\.windows)?(?:\.test)?|ports(?:-inspect|\.test)|ssh-client(?:\.windows\.test)?|update-managed-service-handoff(?:-(?:command|lifecycle)\.test)?|windows-install-roots)\.ts$|src\/shared\/(?:import-specifier|runtime-import)(?:\.test)?\.ts$|src\/test-utils\/openclaw-test-state(?:\.test)?\.ts$|scripts\/(?:android-(?:app-i18n|pin-version)\.ts|ci-run-timings\.mjs|e2e\/lib\/package-compat\.mjs|generate-bundled-channel-config-metadata\.ts|install\.ps1|openclaw-cross-os-release-checks\.ts|plan-release-workflow-matrix\.mjs|run-additional-boundary-checks\.mts|verify-docker-attestations\.mjs|github\/run-openclaw-cross-os-release-checks\.sh|(?:npm-runner|pnpm-runner|ui|vitest-process-group)\.(?:mjs|mts|js)|lib\/(?:direct-run\.(?:mjs|mts)|format-generated-module\.mts|tsx-cli-shim\.mjs|cross-os-release-checks\/[^/]+\.ts))$|test\/scripts\/(?:direct-run-entrypoints|format-generated-module|install-ps1|npm-runner|openclaw-cross-os-release-workflow|pnpm-runner|ui|vitest-process-group)\.test\.ts$|package\.json$|pnpm-lock\.yaml$|pnpm-workspace\.yaml$|\.github\/workflows\/(?:ci|openclaw-cross-os-release-checks-reusable)\.yml$|\.github\/actions\/setup-node-env\/action\.yml$|\.github\/actions\/setup-pnpm-store-cache\/action\.yml$)/;
/^(extensions\/mxc\/|src\/agents\/(?:bash-tools\.exec-script-(?:preflight|target)|bash-tools\.exec\.script-preflight\.test)\.ts$|src\/config\/sessions\/(?:session-accessor\.sqlite-archive(?:\.worker(?:\.test)?)?|store\.session-lifecycle-mutation\.test)\.ts$|src\/process\/|src\/infra\/(?:(?:advertised-lan-host|exec-allowlist-pattern|fs-safe-remove)(?:\.windows)?(?:\.test)?|ports(?:-inspect|\.test)|ssh-client(?:\.windows\.test)?|update-managed-service-handoff(?:-(?:command|lifecycle)\.test)?|windows-install-roots)\.ts$|src\/shared\/(?:import-specifier|runtime-import)(?:\.test)?\.ts$|src\/test-utils\/openclaw-test-state(?:\.test)?\.ts$|scripts\/(?:android-(?:app-i18n|pin-version)\.ts|ci-run-timings\.mjs|e2e\/lib\/package-compat\.mjs|generate-bundled-channel-config-metadata\.ts|install\.ps1|openclaw-cross-os-release-checks\.ts|plan-release-workflow-matrix\.mjs|run-additional-boundary-checks\.mts|verify-docker-attestations\.mjs|github\/run-openclaw-cross-os-release-checks\.sh|tsx\.mjs|(?:npm-runner|pnpm-runner|ui|vitest-process-group)\.(?:mjs|mts|js)|lib\/(?:direct-run\.(?:mjs|mts)|format-generated-module\.mts|tsx-cli-shim\.mjs|cross-os-release-checks\/[^/]+\.ts))$|test\/scripts\/(?:direct-run-entrypoints|format-generated-module|install-ps1|npm-runner|openclaw-cross-os-release-workflow|pnpm-runner|ui|vitest-process-group)\.test\.ts$|package\.json$|pnpm-lock\.yaml$|pnpm-workspace\.yaml$|\.github\/workflows\/(?:ci|openclaw-cross-os-release-checks-reusable)\.yml$|\.github\/actions\/setup-node-env\/action\.yml$|\.github\/actions\/setup-pnpm-store-cache\/action\.yml$)/;
const WINDOWS_TEST_SCOPE_RE =
/^(extensions\/mxc\/test\/(?:mxc-backend|sandbox-policy-loader)\.test\.ts$|src\/agents\/bash-tools\.exec\.script-preflight\.test\.ts$|src\/config\/sessions\/(?:session-accessor\.sqlite-archive\.worker|store\.session-lifecycle-mutation)\.test\.ts$|src\/process\/(?:exec\.windows|supervisor\/supervisor\.anchored-shell\.real|terminal-pty|windows-command)\.test\.ts$|src\/infra\/(?:advertised-lan-host(?:\.windows)?|exec-allowlist-pattern|fs-safe-remove|ports|ssh-client\.windows|update-managed-service-handoff-(?:command|lifecycle)|windows-install-roots)\.test\.ts$|src\/shared\/runtime-import\.test\.ts$|src\/state\/openclaw-database-paths\.windows\.test\.ts$|src\/test-utils\/openclaw-test-state\.test\.ts$|test\/scripts\/(?:direct-run-entrypoints|format-generated-module|npm-runner|openclaw-cross-os-release-workflow|pnpm-runner|ui|vitest-process-group)\.test\.ts$)/;
const WINDOWS_SECRETREF_SCOPE_RE =
+4
View File
@@ -37,6 +37,10 @@ const SYNC_SUPPORT_FILES = [
source: path.join(ROOT, "scripts", "lib", "local-check-runtime.mts"),
target: path.join(".openclaw-sync", "lib", "local-check-runtime.mts"),
},
{
source: path.join(ROOT, "scripts", "tsx.mjs"),
target: path.join(".openclaw-sync", "tsx.mjs"),
},
{
source: path.join(ROOT, "scripts", "lib", "mintlify-accordion.mjs"),
target: path.join(".openclaw-sync", "lib", "mintlify-accordion.mjs"),
@@ -31,6 +31,7 @@ export const PLUGIN_NPM_RELEASE_AUTHORITY_PATHS = [
"scripts/lib/plugin-npm-package-manifest.mts",
"scripts/lib/plugin-npm-release.ts",
"scripts/lib/tsx-cli-shim.mjs",
"scripts/tsx.mjs",
"scripts/plugin-npm-publish.sh",
"scripts/plugin-npm-release-check.ts",
"scripts/plugin-npm-release-plan.ts",
+9 -1
View File
@@ -55,6 +55,14 @@ function resolveTsxImport(checkoutRoot) {
throw resolutionError;
}
export async function registerToolingTsx() {
// tsx indexes the entire shared disk cache before expiration, coupling startup
// to other checkouts' cache size. This flag retains its in-process Map and
// reaches descendant tooling before their loaders initialize.
process.env.TSX_DISABLE_CACHE = "1";
await import(resolveTsxImport(SHIM_CHECKOUT_ROOT));
}
function signalExitCode(signal) {
const signalNumber = osConstants.signals[signal];
return typeof signalNumber === "number" ? 128 + signalNumber : 1;
@@ -118,7 +126,7 @@ async function runTsxCliShimInner(moduleUrl, options) {
try {
const implementationUrl = new URL(options.implementation, moduleUrl);
const implementationPath = fileURLToPath(implementationUrl);
const tsxImport = resolveTsxImport(SHIM_CHECKOUT_ROOT);
const tsxImport = new URL("../tsx.mjs", import.meta.url).href;
const nodeExecutable = process.versions.bun ? "node" : process.execPath;
child = spawn(
nodeExecutable,
+1
View File
@@ -52,6 +52,7 @@ pr_wrapper_components=(
scripts/lib/direct-run.mjs
scripts/lib/tsx-cli-shim.mjs
scripts/lib/local-check-runtime.mts
scripts/tsx.mjs
scripts/verify-pr-hosted-gates.mjs
scripts/verify-pr-hosted-gates.mts
scripts/watch-pr-ci.mjs
+1 -1
View File
@@ -2362,7 +2362,7 @@ const SEMANTIC_TOOLING_TARGET_PATTERNS: Array<[RegExp, string[]]> = [
[/^scripts\/ci-changed-scope\.mjs$/u, [...changedScopeTests, "control-ui-i18n"]],
[/^scripts\/check-changed\.(?:mjs|mts)$/u, ["changed-lanes"]],
[/^scripts\/changed-lanes\.(?:mjs|mts)$/u, ["changed-lanes"]],
[/^scripts\/lib\/tsx-cli-shim\.mjs$/u, ["direct-run-entrypoints"]],
[/^scripts\/(?:lib\/tsx-cli-shim|tsx)\.mjs$/u, ["direct-run-entrypoints"]],
[
new RegExp(
[
+14
View File
@@ -0,0 +1,14 @@
import { registerToolingTsx } from "./lib/tsx-cli-shim.mjs";
// fork() inherits execArgv but can change cwd. Keep our root-script preload
// resolvable there without rewriting unrelated flags or other preloads.
const preload = "./scripts/tsx.mjs";
for (const [index, arg] of process.execArgv.entries()) {
if (arg === preload && process.execArgv[index - 1] === "--import") {
process.execArgv[index] = import.meta.url;
} else if (arg === `--import=${preload}`) {
process.execArgv[index] = `--import=${import.meta.url}`;
}
}
await registerToolingTsx();
+15 -9
View File
@@ -253,16 +253,20 @@ describe("test scripts", () => {
scripts?: Record<string, string>;
};
expect(pkg.scripts?.["test:serial"]).toBe("node --import tsx scripts/test-projects-serial.mts");
expect(pkg.scripts?.["test:max"]).toBe("node --import tsx scripts/test-projects-max.mts");
expect(pkg.scripts?.["test:serial"]).toBe(
"node --import ./scripts/tsx.mjs scripts/test-projects-serial.mts",
);
expect(pkg.scripts?.["test:max"]).toBe(
"node --import ./scripts/tsx.mjs scripts/test-projects-max.mts",
);
expect(pkg.scripts?.["test:changed:max"]).toBe(
"node --import tsx scripts/test-projects-max.mts --changed origin/main",
"node --import ./scripts/tsx.mjs scripts/test-projects-max.mts --changed origin/main",
);
expect(pkg.scripts?.["test:perf:imports"]).toBe(
"node --import tsx scripts/test-projects-imports.mts",
"node --import ./scripts/tsx.mjs scripts/test-projects-imports.mts",
);
expect(pkg.scripts?.["test:perf:imports:changed"]).toBe(
"node --import tsx scripts/test-projects-imports.mts --changed origin/main",
"node --import ./scripts/tsx.mjs scripts/test-projects-imports.mts --changed origin/main",
);
expect(pkg.scripts?.["test:fast"]).toBe(
"node scripts/run-vitest.mjs run --config test/vitest/vitest.unit.config.ts",
@@ -274,12 +278,14 @@ describe("test scripts", () => {
"node scripts/run-vitest.mjs run --config test/vitest/vitest.unit-fast.config.ts",
);
expect(pkg.scripts?.["test:unit:fast:audit"]).toBe(
"node --import tsx scripts/test-unit-fast-audit.mts",
"node --import ./scripts/tsx.mjs scripts/test-unit-fast-audit.mts",
);
expect(pkg.scripts?.["test"]).toBe("node --import ./scripts/tsx.mjs scripts/test-projects.mts");
expect(pkg.scripts?.["test:force"]).toBe(
"node --import ./scripts/tsx.mjs scripts/test-force.ts",
);
expect(pkg.scripts?.["test"]).toBe("node --import tsx scripts/test-projects.mts");
expect(pkg.scripts?.["test:force"]).toBe("node --import tsx scripts/test-force.ts");
expect(pkg.scripts?.["test:gateway"]).toBe(
"node --import tsx scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts",
"node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_GATEWAY_PROJECT_SHARDS=1 -- node scripts/run-vitest.mjs run --config test/vitest/vitest.gateway.config.ts",
);
expect(pkg.scripts?.["test:single"]).toBeUndefined();
});
+22 -15
View File
@@ -98,7 +98,7 @@ describe("package scripts", () => {
it("finds node script targets after env assignments and valued node options", () => {
expect(
extractNodeScriptTargets(
"FOO=1 node --import tsx scripts/release-check.ts && node --max-old-space-size=8192 --import tsx scripts/plugin-sdk-surface-report.mts && env BAR=1 node -r tsx scripts/check.ts",
"FOO=1 node --import ./scripts/tsx.mjs scripts/release-check.ts && node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/plugin-sdk-surface-report.mts && env BAR=1 node -r ./preload.cjs scripts/check.ts",
),
).toEqual([
"scripts/release-check.ts",
@@ -142,31 +142,36 @@ describe("package scripts", () => {
{ scriptName: "build:docker", expectedCount: 2 },
{ scriptName: "build:plugin-sdk:strict-smoke", expectedCount: 1 },
{ scriptName: "build:strict-smoke", expectedCount: 1 },
])("runs TypeScript steps in $scriptName through tsx", ({ scriptName, expectedCount }) => {
const script = expectDefined(
readPackageJson().scripts[scriptName],
`package script ${scriptName}`,
);
])(
"runs TypeScript steps in $scriptName through the tooling bootstrap",
({ scriptName, expectedCount }) => {
const script = expectDefined(
readPackageJson().scripts[scriptName],
`package script ${scriptName}`,
);
expect(script).not.toContain("--experimental-strip-types");
expect(script.match(/node --import tsx scripts\/[^\s]+\.ts/gu)).toHaveLength(expectedCount);
});
expect(script).not.toContain("--experimental-strip-types");
expect(
script.match(/node --import \.\/scripts\/tsx\.mjs scripts\/[^\s]+\.ts(?=\s|$)/gu),
).toHaveLength(expectedCount);
},
);
it("enables live cache validation in the package script", () => {
expect(readPackageJson().scripts["test:live:cache"]).toBe(
"node --import tsx scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 -- node --import tsx scripts/check-live-cache.ts",
"node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_LIVE_TEST=1 OPENCLAW_LIVE_CACHE_TEST=1 -- node --import ./scripts/tsx.mjs scripts/check-live-cache.ts",
);
});
it("runs browser extension bootstrap E2E against real Chromium", () => {
expect(readPackageJson().scripts["test:e2e:browser-extension"]).toBe(
"node --import tsx scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers -- node --import tsx scripts/ensure-playwright-chromium.mts --require-playwright-chromium && node --import tsx scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers OPENCLAW_BROWSER_EXTENSION_E2E=1 OPENCLAW_E2E_WORKERS=1 -- node scripts/run-vitest.mjs extensions/browser/chrome-extension/bootstrap.chromium.test.ts",
"node --import ./scripts/tsx.mjs scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers -- node --import ./scripts/tsx.mjs scripts/ensure-playwright-chromium.mts --require-playwright-chromium && node --import ./scripts/tsx.mjs scripts/run-with-env.mts PLAYWRIGHT_BROWSERS_PATH=.artifacts/playwright-browsers OPENCLAW_BROWSER_EXTENSION_E2E=1 OPENCLAW_E2E_WORKERS=1 -- node scripts/run-vitest.mjs extensions/browser/chrome-extension/bootstrap.chromium.test.ts",
);
});
it("gives the plugin SDK usage scan enough heap for repository-wide analysis", () => {
expect(readPackageJson().scripts["plugin-sdk:usage"]).toBe(
"node --max-old-space-size=8192 --import tsx scripts/analyze-plugin-sdk-usage.ts",
"node --max-old-space-size=8192 --import ./scripts/tsx.mjs scripts/analyze-plugin-sdk-usage.ts",
);
});
@@ -178,7 +183,7 @@ describe("package scripts", () => {
it("runs runtime postbuild before plugin SDK strict export checks", () => {
expect(readPackageJson().scripts["build:plugin-sdk:strict-smoke"]).toBe(
"node --import tsx scripts/tsdown-build.mts && node scripts/runtime-postbuild.mjs && node --import tsx scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/check-plugin-sdk-exports.mts",
"node --import ./scripts/tsx.mjs scripts/tsdown-build.mts && node scripts/runtime-postbuild.mjs && node --import ./scripts/tsx.mjs scripts/run-with-env.mts OPENCLAW_PLUGIN_SDK_CANONICAL_DTS=1 -- node --import ./scripts/tsx.mjs scripts/write-plugin-sdk-entry-dts.ts && node --import ./scripts/tsx.mjs scripts/check-plugin-sdk-exports.mts",
);
});
@@ -196,9 +201,11 @@ describe("package scripts", () => {
it("cleans package builds before validating release contents", () => {
const scripts = readPackageJson().scripts;
expect(scripts["build:package"]).toBe("node --import tsx scripts/build-all.mts package");
expect(scripts["build:package"]).toBe(
"node --import ./scripts/tsx.mjs scripts/build-all.mts package",
);
expect(scripts["release:check"]).toBe(
"pnpm build:package && pnpm release:generated:check && node --import tsx scripts/release-check.ts",
"pnpm build:package && pnpm release:generated:check && node --import ./scripts/tsx.mjs scripts/release-check.ts",
);
});
+2
View File
@@ -833,6 +833,8 @@ describe("collectPluginNpmGitRangeSelection", () => {
"packages/plugin-package-contract/src/schema.ts",
"scripts/lib/plugin-publication-candidates.ts",
"scripts/lib/plugin-publication-collector.ts",
"scripts/lib/tsx-cli-shim.mjs",
"scripts/tsx.mjs",
"scripts/plugin-npm-release-plan.ts",
])("selects all publishable plugins for an authority-only %s change", (changedPath) => {
const repoDir = makeTempRepoRoot(tempDirs, "openclaw-plugin-npm-range-");
+257 -23
View File
@@ -1,15 +1,19 @@
import { spawnSync } from "node:child_process";
import {
copyFileSync,
existsSync,
mkdirSync,
mkdtempSync,
readFileSync,
readdirSync,
realpathSync,
rmSync,
writeFileSync,
} from "node:fs";
import { tmpdir } from "node:os";
import { createRequire } from "node:module";
import { tmpdir, userInfo } from "node:os";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { describe, expect, it } from "vitest";
import { detectChangedScope } from "../../scripts/ci-changed-scope.mjs";
import { isDirectRunPath } from "../../scripts/lib/direct-run.mjs";
@@ -109,12 +113,14 @@ function writeTsxFixture(modulesDir: string, marker: string) {
writeFileSync(path.join(dependencyDir, "index.js"), 'export const value = "loaded";\n');
}
function runShimFixture(
function withShimFixture<T>(
wrapper: (typeof TSX_SHIM_WRAPPERS)[number],
configureModules: (paths: {
run: (paths: {
checkoutRoot: string;
fixtureRoot: string;
}) => ModulesEnv = () => ({}),
implementationPath: string;
wrapperPath: string;
}) => T,
) {
const fixtureRoot = realpathSync(mkdtempSync(path.join(tmpdir(), "openclaw-tsx-cli-shim-")));
const checkoutRoot = path.join(fixtureRoot, "checkout");
@@ -124,6 +130,7 @@ function runShimFixture(
mkdirSync(path.dirname(wrapperPath), { recursive: true });
mkdirSync(path.join(checkoutRoot, "scripts", "lib"), { recursive: true });
copyFileSync(wrapper, wrapperPath);
copyFileSync("scripts/tsx.mjs", path.join(checkoutRoot, "scripts", "tsx.mjs"));
copyFileSync(
"scripts/lib/tsx-cli-shim.mjs",
path.join(checkoutRoot, "scripts", "lib", "tsx-cli-shim.mjs"),
@@ -133,30 +140,45 @@ function runShimFixture(
path.join(checkoutRoot, "scripts", "lib", "local-check-runtime.mts"),
);
writeFileSync(path.join(checkoutRoot, "pnpm-lock.yaml"), "lockfileVersion: '9.0'\n");
writeFileSync(
implementationPath,
'import { value } from "shim-dependency";\nprocess.stdout.write(JSON.stringify({ loader: process.env.OPENCLAW_TSX_FIXTURE_LOADER, dependency: value, args: process.argv.slice(2) }));\n',
);
writeTsxFixture(path.join(checkoutRoot, "node_modules"), "checkout");
const modulesEnv = configureModules({ checkoutRoot, fixtureRoot });
const env = { ...process.env };
delete env.NODE_OPTIONS;
delete env.NODE_PATH;
delete env.PNPM_CONFIG_MODULES_DIR;
delete env.npm_config_modules_dir;
Object.assign(env, modulesEnv);
return spawnSync(process.execPath, [wrapperPath, "--hydrated-proof"], {
cwd: fixtureRoot,
encoding: "utf8",
env,
timeout: 10_000,
});
return run({ checkoutRoot, fixtureRoot, implementationPath, wrapperPath });
} finally {
rmSync(fixtureRoot, { recursive: true, force: true });
}
}
function runShimFixture(
wrapper: (typeof TSX_SHIM_WRAPPERS)[number],
configureModules: (paths: {
checkoutRoot: string;
fixtureRoot: string;
}) => ModulesEnv = () => ({}),
) {
return withShimFixture(
wrapper,
({ checkoutRoot, fixtureRoot, implementationPath, wrapperPath }) => {
writeFileSync(
implementationPath,
'import { value } from "shim-dependency";\nprocess.stdout.write(JSON.stringify({ loader: process.env.OPENCLAW_TSX_FIXTURE_LOADER, dependency: value, args: process.argv.slice(2) }));\n',
);
writeTsxFixture(path.join(checkoutRoot, "node_modules"), "checkout");
const modulesEnv = configureModules({ checkoutRoot, fixtureRoot });
const env = { ...process.env };
delete env.NODE_OPTIONS;
delete env.NODE_PATH;
delete env.PNPM_CONFIG_MODULES_DIR;
delete env.npm_config_modules_dir;
Object.assign(env, modulesEnv);
return spawnSync(process.execPath, [wrapperPath, "--hydrated-proof"], {
cwd: fixtureRoot,
encoding: "utf8",
env,
timeout: 10_000,
});
},
);
}
function expectShimLoader(result: ReturnType<typeof runShimFixture>, loader: string) {
expect(result.error).toBeUndefined();
expect(result.status, result.stderr).toBe(0);
@@ -168,6 +190,217 @@ function expectShimLoader(result: ReturnType<typeof runShimFixture>, loader: str
}
describe("script direct-run entrypoints", () => {
it.each([false, true])(
"preserves preloads when forking into another cwd (equals=%s)",
(equals) => {
withShimFixture(TSX_SHIM_WRAPPERS[0], ({ checkoutRoot, fixtureRoot, implementationPath }) => {
const forkCwd = path.join(fixtureRoot, "child cwd");
mkdirSync(forkCwd);
const childPath = path.join(fixtureRoot, "fork-child.mts");
const extraPreloadPath = path.join(fixtureRoot, "extra-preload.mjs");
writeFileSync(extraPreloadPath, 'globalThis.fixturePreload = "preserved";\n');
const snapshotSource = `
enum Transformed { Value = "transformed" }
console.log(JSON.stringify({ transformed: Transformed.Value, preload: globalThis.fixturePreload,
args: process.argv.slice(2), cwd: process.cwd(), execArgv: process.execArgv }));
`;
writeFileSync(childPath, `${snapshotSource}\nprocess.exitCode = 17;\n`);
writeFileSync(
implementationPath,
`${snapshotSource}
import { fork } from "node:child_process";
const child = fork(${JSON.stringify(childPath)}, process.argv.slice(2), {
cwd: ${JSON.stringify(forkCwd)}, stdio: "inherit",
});
process.exitCode = await new Promise((resolve, reject) => {
child.once("error", reject);
child.once("exit", code => resolve(code ?? 1));
});
`,
);
const nodeFlags = ["--no-warnings", "--import", pathToFileURL(extraPreloadPath).href];
const trailingFlags = ["--title", "./scripts/tsx.mjs", "--import=node:fs"];
const preload = equals ? ["--import=./scripts/tsx.mjs"] : ["--import", "./scripts/tsx.mjs"];
const bootstrapUrl = pathToFileURL(path.join(checkoutRoot, "scripts/tsx.mjs")).href;
const expectedPreload = equals ? [`--import=${bootstrapUrl}`] : ["--import", bootstrapUrl];
const env: NodeJS.ProcessEnv = {
...process.env,
TMPDIR: fixtureRoot,
TMP: fixtureRoot,
TEMP: fixtureRoot,
PNPM_CONFIG_MODULES_DIR: path.dirname(
path.dirname(createRequire(import.meta.url).resolve("tsx/package.json")),
),
};
delete env.TSX_DISABLE_CACHE;
delete env.NODE_OPTIONS;
const result = spawnSync(
process.execPath,
[
...nodeFlags,
...preload,
...trailingFlags,
implementationPath,
"argument with spaces",
"--fork-proof",
],
{
cwd: checkoutRoot,
encoding: "utf8",
env,
timeout: 10_000,
},
);
expect(result.error).toBeUndefined();
expect(result.status, result.stderr).toBe(17);
expect(
result.stdout
.trim()
.split("\n")
.map((line) => JSON.parse(line)),
).toEqual(
[checkoutRoot, forkCwd].map((cwd) => ({
transformed: "transformed",
preload: "preserved",
args: ["argument with spaces", "--fork-proof"],
cwd,
execArgv: [...nodeFlags, ...expectedPreload, ...trailingFlags],
})),
);
});
},
);
it.each(["wrapper", "root package preloads"])(
"keeps %s and raw tsx children off disk caches without changing other cache settings",
(entrypoint) => {
withShimFixture(TSX_SHIM_WRAPPERS[0], ({ fixtureRoot, implementationPath, wrapperPath }) => {
const require = createRequire(import.meta.url);
const modulesDir = path.dirname(path.dirname(require.resolve("tsx/package.json")));
const tempRoot = path.join(fixtureRoot, "temp");
const cacheRoots = ["tsx", `tsx-${process.geteuid?.() ?? userInfo().username}`].map(
(name) => path.join(tempRoot, name),
);
for (const cacheRoot of cacheRoots) {
mkdirSync(cacheRoot, { recursive: true });
writeFileSync(path.join(cacheRoot, "0-sentinel"), "keep");
}
const accessLog = path.join(fixtureRoot, "cache-access.log");
const guard = path.join(fixtureRoot, "cache-guard.cjs");
writeFileSync(
guard,
`
const fs = require("node:fs");
const path = require("node:path");
const readdirSync = fs.readdirSync;
fs.readdirSync = function (directory, ...args) {
if (/^tsx(?:-|$)/.test(path.basename(String(directory)))) {
fs.appendFileSync(${JSON.stringify(accessLog)}, "cache scan\\n");
throw new Error("Unexpected tsx disk cache access");
}
return readdirSync.call(this, directory, ...args);
};
`,
);
const preservedEnv = Object.fromEntries(
[
"TMPDIR",
"TMP",
"TEMP",
"XDG_CACHE_HOME",
"NODE_COMPILE_CACHE",
"OPENCLAW_VITEST_FS_MODULE_CACHE_PATH",
].map((key) => [
key,
key === "TMPDIR" || key === "TEMP" ? tempRoot : path.join(fixtureRoot, key),
]),
);
const childPath = path.join(fixtureRoot, "child.mts");
const snapshotSource = `
enum Transformed { Value = "transformed" }
console.log(JSON.stringify({
transformed: Transformed.Value,
args: process.argv.slice(2),
cwd: process.cwd(),
env: Object.fromEntries(${JSON.stringify(Object.keys(preservedEnv))}.map(key => [key, process.env[key]])),
}));
`;
writeFileSync(childPath, `${snapshotSource}\nprocess.exitCode = 17;\n`);
writeFileSync(
implementationPath,
`${snapshotSource}
import { spawnSync } from "node:child_process";
const child = spawnSync(process.execPath, ["--import", "tsx", ${JSON.stringify(childPath)}, ...process.argv.slice(2)], { stdio: "inherit" });
if (child.error) throw child.error;
process.exitCode = child.status ?? 1;
`,
);
const { scripts } = JSON.parse(readFileSync("package.json", "utf8")) as {
scripts: Record<string, string>;
};
const preloads = [
...new Set(
Object.values(scripts).flatMap((command) =>
[...command.matchAll(/--import(?:=|\s+)(\S+)/gu)].map((match) => match[1]!),
),
),
];
expect(preloads.length).toBeGreaterThan(0);
const launches =
entrypoint === "wrapper"
? [[wrapperPath]]
: preloads.map((preload) => ["--import", preload, implementationPath]);
for (const cacheFlag of [undefined, ""]) {
const env: NodeJS.ProcessEnv = {
...process.env,
...preservedEnv,
PNPM_CONFIG_MODULES_DIR: modulesDir,
NODE_OPTIONS: `--require ${JSON.stringify(guard)}`,
};
delete env.TSX_DISABLE_CACHE;
if (cacheFlag !== undefined) {
env.TSX_DISABLE_CACHE = cacheFlag;
}
for (const launch of launches) {
const result = spawnSync(
process.execPath,
[...launch, "argument with spaces", "--proof"],
{
cwd: process.cwd(),
encoding: "utf8",
env,
timeout: 10_000,
},
);
expect(result.error).toBeUndefined();
expect(result.status, result.stderr).toBe(17);
expect(
result.stdout
.trim()
.split("\n")
.map((line) => JSON.parse(line)),
).toEqual(
Array.from({ length: 2 }, () => ({
transformed: "transformed",
args: ["argument with spaces", "--proof"],
cwd: process.cwd(),
env: preservedEnv,
})),
);
if (entrypoint === "wrapper") {
expect(result.stderr.trim().split("\n").at(-1)).toBe("[test] FAILED (exit 17)");
}
}
}
expect(existsSync(accessLog)).toBe(false);
for (const cacheRoot of cacheRoots) {
expect(readdirSync(cacheRoot)).toEqual(["0-sentinel"]);
expect(readFileSync(path.join(cacheRoot, "0-sentinel"), "utf8")).toBe("keep");
}
});
},
);
it.each(EXECUTABLE_ENTRYPOINTS)("runs $script through its guarded CLI", (entrypoint) => {
const result = runEntrypoint(entrypoint);
const output = `${result.stdout}${result.stderr}`;
@@ -257,6 +490,7 @@ describe("script direct-run entrypoints", () => {
"scripts/lib/direct-run.mjs",
"scripts/lib/tsx-cli-shim.mjs",
"test/scripts/direct-run-entrypoints.test.ts",
"scripts/tsx.mjs",
])("routes %s through Windows CI", (changedPath) => {
expect(detectChangedScope([changedPath]).runWindows).toBe(true);
});
@@ -616,6 +616,7 @@ describe("scripts/test-docker-all scheduler", () => {
copyFileSync("scripts/test-docker-all.mjs", path.join(scriptsDir, "test-docker-all.mjs"));
copyFileSync("scripts/test-docker-all.mts", path.join(scriptsDir, "test-docker-all.mts"));
copyFileSync("scripts/lib/tsx-cli-shim.mjs", path.join(libDir, "tsx-cli-shim.mjs"));
copyFileSync("scripts/tsx.mjs", path.join(scriptsDir, "tsx.mjs"));
copyFileSync(
"scripts/prepublish-plugin-registry-artifact.mjs",
path.join(scriptsDir, "prepublish-plugin-registry-artifact.mjs"),
@@ -7258,9 +7258,10 @@ describe("package artifact reuse", () => {
const postpublishEvidence = workflowStep(releasePublishJob, "Upload postpublish evidence");
expect(packageJson.scripts).toMatchObject({
"release:verify-beta": "node --import tsx scripts/release-verify-beta.ts",
"release:candidate": "node --import tsx scripts/release-candidate-checklist.mts",
"release:beta": "node --import tsx scripts/release-candidate-checklist.mts",
"release:verify-beta": "node --import ./scripts/tsx.mjs scripts/release-verify-beta.ts",
"release:candidate":
"node --import ./scripts/tsx.mjs scripts/release-candidate-checklist.mts",
"release:beta": "node --import ./scripts/tsx.mjs scripts/release-candidate-checklist.mts",
"release:fast-pretag-check": "bash scripts/release-fast-pretag-check.sh",
});
expect(workflowStep(releasePublishJob, "Setup Node environment").with).toMatchObject({
+1
View File
@@ -214,6 +214,7 @@ function installPrCliFixture(repoDir: string) {
"scripts/lib/direct-run.mjs",
"scripts/lib/tsx-cli-shim.mjs",
"scripts/lib/local-check-runtime.mts",
"scripts/tsx.mjs",
"scripts/pr-lib/worktree.sh",
"scripts/pr-lib/operation-lock.sh",
"scripts/pr-lib/process-group-runner.mjs",
+15
View File
@@ -91,6 +91,7 @@ function makeMismatchedWrapperRepo() {
"scripts/lib/local-check-runtime.mts",
join(canonical, "scripts", "lib", "local-check-runtime.mts"),
);
cpSync("scripts/tsx.mjs", join(canonical, "scripts", "tsx.mjs"));
writeFileSync(
join(canonical, "scripts", "lib", "plain-gh.sh"),
"resolve_plain_gh_bin() { printf '/usr/bin/true\\n'; }\ngh_plain() { :; }\n",
@@ -205,6 +206,7 @@ describe("scripts/pr wrappers", () => {
expect(script).toContain("scripts/verify-pr-hosted-gates.mjs");
expect(script).toContain("scripts/verify-pr-hosted-gates.mts");
expect(script).toContain("scripts/lib/tsx-cli-shim.mjs");
expect(script).toContain("scripts/tsx.mjs");
expect(script).toContain("scripts/lib/plain-gh.mjs");
expect(script).toContain("scripts/lib/direct-run.mjs");
expect(script).toContain("scripts/pr review-init <PR>");
@@ -443,6 +445,7 @@ describe("scripts/pr wrappers", () => {
writeFileSync(join(repo, "scripts", "lib", "direct-run.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "lib", "tsx-cli-shim.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "lib", "local-check-runtime.mts"), "// canonical\n");
writeFileSync(join(repo, "scripts", "tsx.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "watch-pr-ci.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "watch-pr-ci.mts"), "// canonical\n");
writeFileSync(join(repo, "scripts", "verify-pr-hosted-gates.mjs"), "// canonical\n");
@@ -477,6 +480,17 @@ describe("scripts/pr wrappers", () => {
expect(git(linked, ["restore", component]).status).toBe(0);
}
writeFileSync(join(linked, "scripts", "tsx.mjs"), "// dirty preloader\n");
const dirtyPreloaderResult = spawnSync(join(linked, "scripts", "pr"), ["ls"], {
cwd: linked,
encoding: "utf8",
});
expect(dirtyPreloaderResult.status).toBe(1);
expect(dirtyPreloaderResult.stderr).toContain(
"scripts/pr wrapper files have uncommitted changes",
);
expect(git(linked, ["restore", "scripts/tsx.mjs"]).status).toBe(0);
// A dirty canonical checkout no longer blocks a linked worktree whose
// committed wrapper matches the origin/main trust anchor; without that
// anchor it must still refuse.
@@ -520,6 +534,7 @@ describe("scripts/pr wrappers", () => {
writeFileSync(join(repo, "scripts", "lib", "direct-run.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "lib", "tsx-cli-shim.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "lib", "local-check-runtime.mts"), "// canonical\n");
writeFileSync(join(repo, "scripts", "tsx.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "watch-pr-ci.mjs"), "// canonical\n");
writeFileSync(join(repo, "scripts", "watch-pr-ci.mts"), "// canonical\n");
writeFileSync(join(repo, "scripts", "verify-pr-hosted-gates.mjs"), "// canonical\n");
+54 -12
View File
@@ -129,6 +129,7 @@ function makeIsolatedPreflightFixture(params: Parameters<typeof makeReleaseFixtu
const files = [
"scripts/release-preflight.mjs",
"scripts/release-preflight.mts",
"scripts/tsx.mjs",
"scripts/windows-cmd-helpers.mjs",
"scripts/lib/error-format.mts",
"scripts/lib/failed-trailer.mts",
@@ -336,22 +337,63 @@ describe("scripts/release-preflight.mjs", () => {
);
});
it("uses bounded parallelism for independent checks", () => {
it.each([1, 2, 3])("uses bounded parallelism for independent checks with jobs=%i", (jobs) => {
const fakePnpm = makeFakePnpm();
const root = makeReleaseFixture();
const env = { OPENCLAW_RELEASE_PREFLIGHT_DELAY_MS: "120" };
const commands = [
"pnpm config:schema:check",
"pnpm config:channels:check",
"pnpm config:docs:check",
];
const observerPath = join(root, "observe-concurrency.cjs");
const resultPath = join(root, "concurrency.json");
writeFileSync(
observerPath,
`const childProcess = require("node:child_process");
const { writeFileSync } = require("node:fs");
const { syncBuiltinESMExports } = require("node:module");
const commands = ${JSON.stringify(commands)};
const originalSpawn = childProcess.spawn;
let active = 0;
let maxActive = 0;
let total = 0;
childProcess.spawn = function (...args) {
const child = originalSpawn.apply(this, args);
if (commands.includes([args[0], ...(args[1] ?? [])].join(" "))) {
active += 1;
total += 1;
maxActive = Math.max(maxActive, active);
child.once("close", () => { active -= 1; });
}
return child;
};
syncBuiltinESMExports();
process.once("exit", () => {
if (total > 0) {
writeFileSync(${JSON.stringify(resultPath)}, JSON.stringify({ maxActive, total, active }));
}
});
`,
);
const serialStartedAt = performance.now();
const serial = runPreflight(["--scope", "config", "--jobs", "1"], fakePnpm, env, root);
const serialMs = performance.now() - serialStartedAt;
// Count real managed commands from synchronous admission through close, excluding
// loader startup time. Inherited observers with no matching commands write nothing.
const result = runPreflight(
["--scope", "config", "--jobs", String(jobs)],
fakePnpm,
{
NODE_OPTIONS: `${process.env.NODE_OPTIONS ?? ""} --require ${JSON.stringify(observerPath)}`,
},
root,
);
const parallelStartedAt = performance.now();
const parallel = runPreflight(["--scope", "config", "--jobs", "3"], fakePnpm, env, root);
const parallelMs = performance.now() - parallelStartedAt;
expect(serial.status).toBe(0);
expect(parallel.status).toBe(0);
expect(parallelMs).toBeLessThan(serialMs * 0.75);
expect(result.status, result.stderr).toBe(0);
expect(JSON.parse(readFileSync(resultPath, "utf8"))).toEqual({
maxActive: Math.min(jobs, commands.length),
total: commands.length,
active: 0,
});
expect(readPnpmLog(fakePnpm.logPath).toSorted()).toEqual(commands.toSorted());
});
it("accepts base macOS metadata for a beta package version", () => {
+5 -5
View File
@@ -239,13 +239,13 @@ describe("run-oxlint", () => {
};
const shardedLintRunner = readFileSync("scripts/run-oxlint-shards.mts", "utf8");
expect(packageJson.scripts.check).toBe("node --import tsx scripts/check.mts");
expect(packageJson.scripts.lint).toBe("node --import tsx scripts/run-lint.mts");
expect(packageJson.scripts.check).toBe("node --import ./scripts/tsx.mjs scripts/check.mts");
expect(packageJson.scripts.lint).toBe("node --import ./scripts/tsx.mjs scripts/run-lint.mts");
expect(packageJson.scripts["lint:core"]).toBe(
"node --import tsx scripts/run-oxlint-shards.mts --only=core",
"node --import ./scripts/tsx.mjs scripts/run-oxlint-shards.mts --only=core",
);
expect(packageJson.scripts.check).not.toContain(
"node --import tsx scripts/prepare-extension-package-boundary-artifacts.mts",
"node --import ./scripts/tsx.mjs scripts/prepare-extension-package-boundary-artifacts.mts",
);
expect(shardedLintRunner).toContain("prepare-extension-package-boundary-artifacts.mts");
expect(shardedLintRunner).toContain('OPENCLAW_OXLINT_SKIP_PREPARE: "1"');
@@ -257,7 +257,7 @@ describe("run-oxlint", () => {
};
const lintRunner = readFileSync("scripts/run-lint.mts", "utf8");
expect(packageJson.scripts.lint).toBe("node --import tsx scripts/run-lint.mts");
expect(packageJson.scripts.lint).toBe("node --import ./scripts/tsx.mjs scripts/run-lint.mts");
expect(lintRunner.indexOf("ensureRepoToolNodeModulesLink(")).toBeGreaterThan(-1);
expect(
lintRunner.indexOf('path.resolve("scripts", "control-ui-i18n-verify.ts")'),
+6 -6
View File
@@ -232,12 +232,12 @@ describe("scripts/test-projects changed-target routing", () => {
}
});
it("routes shared TypeScript CLI shim changes through wrapper tests", () => {
expectChangedTargets(
["scripts/lib/tsx-cli-shim.mjs"],
["test/scripts/direct-run-entrypoints.test.ts"],
);
});
it.each(["scripts/lib/tsx-cli-shim.mjs", "scripts/tsx.mjs"])(
"routes shared TypeScript tooling changes through wrapper tests for %s",
(scriptPath) => {
expectChangedTargets([scriptPath], ["test/scripts/direct-run-entrypoints.test.ts"]);
},
);
it("routes Docker pull retry helper changes through its regression test", () => {
expectChangedTargets(