From 609d60a3562142350d6afb3f824b0248624a00d0 Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Wed, 9 Sep 2026 10:19:51 -0700 Subject: [PATCH 1/4] chore(node): remove redundant experimental type-stripping flags Signed-off-by: Carlos Villela --- .../SKILL.md | 4 +- .../SKILL.md | 2 +- .../SKILL.md | 2 +- .../SKILL.md | 2 +- .../nemoclaw-maintainer-day/HOTSPOTS.md | 4 +- .../skills/nemoclaw-maintainer-day/SKILL.md | 8 +-- .../scripts/check-gates.ts | 2 +- .../scripts/handoff-summary.ts | 2 +- .../scripts/hotspots.ts | 2 +- .../scripts/run-trusted-check-gates.sh | 2 +- .../nemoclaw-maintainer-day/scripts/state.ts | 2 +- .../nemoclaw-maintainer-day/scripts/triage.ts | 2 +- .../scripts/version-progress.ts | 2 +- .../scripts/version-target.ts | 2 +- .../nemoclaw-maintainer-evening/SKILL.md | 4 +- .../scripts/run-trusted-policy.sh | 2 +- .../nemoclaw-maintainer-morning/SKILL.md | 8 +-- .../SKILL.md | 6 +- .../scripts/normalize-title-tags.ts | 4 +- .../refresh_locked_npm_cache_seed/index.ts | 1 - .../actions/ci-compile-artifacts/action.yaml | 6 +- .github/actions/ci-install-dependencies.sh | 2 +- .../actions/ci-reviewed-npm-audit/action.yaml | 4 +- .github/actions/ci-static-checks/action.yaml | 2 +- .../workflows/candidate-compatibility.yaml | 16 ++--- .github/workflows/code-scanning.yaml | 2 +- .github/workflows/e2e-main-retry.yaml | 4 +- .github/workflows/e2e.yaml | 34 ++++----- .github/workflows/hosted-runner-recovery.yaml | 2 +- .github/workflows/llama-cpp-image.yaml | 2 +- .github/workflows/managed-images.yaml | 6 +- ...ative-runtime-qualification-collector.yaml | 2 +- .../workflows/openshell-sdk-package-pr.yaml | 2 +- .github/workflows/podman-cpu-proof.yaml | 10 +-- .github/workflows/portable-profile-e2e.yaml | 2 +- .github/workflows/post-merge-docs.yaml | 8 +-- .../workflows/pr-merge-conflict-fixer.yaml | 16 ++--- .github/workflows/pr-review-advisor.yaml | 14 ++-- .github/workflows/pr-self-hosted.yaml | 2 +- .github/workflows/pr.yaml | 2 +- .github/workflows/release-latest-tag.yaml | 2 +- .github/workflows/sandbox-images.yaml | 10 +-- .pre-commit-config.yaml | 2 +- Dockerfile | 70 +++++++++---------- Dockerfile.base | 24 +++---- agents/hermes/Dockerfile | 16 ++--- agents/hermes/Dockerfile.base | 10 +-- agents/hermes/image-build-probes.py | 2 +- agents/langchain-deepagents-code/Dockerfile | 8 +-- .../langchain-deepagents-code/Dockerfile.base | 10 +-- agents/openclaw/dependency-review.md | 2 +- agents/pi/Dockerfile | 8 +-- agents/pi/Dockerfile.base | 10 +-- docs/resources/starter-prompt.md | 6 +- docs/security/advisory-early-warning.md | 4 +- package.json | 6 +- scripts/advisory-early-warning-scan.mts | 2 +- scripts/audit-reviewed-npm-graph.mts | 2 +- scripts/check-installer-hash.sh | 2 +- .../check-messaging-plan-image-boundary.mts | 4 +- .../checks/build-protected-managed-images.sh | 12 ++-- ...nerate-managed-startup-profile-fixture.mts | 2 +- .../checks/package-openshell-sdk-for-pr.mts | 2 +- scripts/checks/prepare-ci-npm-install.mts | 2 +- .../checks/run-managed-image-direct-e2e.ts | 2 +- scripts/dev-tier-selector.mts | 2 +- scripts/generate-openclaw-config.mts | 2 +- scripts/install.sh | 4 +- scripts/lib/npm-audit-receipt.mts | 2 +- scripts/lib/openclaw-npm-remediation.mts | 2 +- scripts/lib/patch-bundled-npm-ip-address.mts | 2 +- scripts/lib/reviewed-npm-archive.mts | 2 +- scripts/lib/reviewed-npm-audit.mts | 2 +- scripts/lib/seed-reviewed-npm-cache.mts | 2 +- scripts/local-credential-helper.mts | 2 +- .../patch-gateway-daemon-dialback.mts | 2 +- scripts/patch-bundled-npm-brace-expansion.mts | 2 +- scripts/patch-bundled-npm-tar.mts | 2 +- scripts/patch-openclaw-chat-send.mts | 2 +- .../patch-openclaw-issue-4434-diagnostics.mts | 2 +- ...openclaw-managed-transport-diagnostics.mts | 2 +- scripts/patch-openclaw-mcp-npx.mts | 2 +- scripts/patch-openclaw-mcp-reliability.mts | 2 +- .../patch-openclaw-mcp-tools-list-timeout.mts | 2 +- ...atch-openclaw-shared-state-permissions.mts | 2 +- scripts/patch-openclaw-tool-catalog.mts | 2 +- scripts/prepare-dual-dgx-station.mts | 2 +- scripts/retire-release-label.mts | 2 +- scripts/shellcheck-json1-to-sarif.mts | 2 +- scripts/update-hermes-agent.sh | 2 +- scripts/upgrade-bundled-npm.mts | 2 +- scripts/validate-openclaw-tool-search.mts | 2 +- .../bedrock-runtime-adapter-cleanup.test.ts | 3 +- src/lib/hermes-tool-gateway-broker.ts | 4 +- .../inference/bedrock-runtime-adapter.test.ts | 8 +-- src/lib/inference/local-adapter-lifecycle.ts | 2 +- .../applier/build/messaging-build-applier.mts | 3 +- .../post-agent-install-selection.test.ts | 1 - ...ckerfile-remote-dashboard-bind-contract.ts | 18 ++--- .../managed-startup-image-runtime.test.ts | 1 - .../onboard/managed-startup/image-runtime.ts | 5 -- .../langchain-deepagents-code-config.test.ts | 2 +- .../langchain-deepagents-code-image.test.ts | 2 +- ...ain-deepagents-code-provider-label.test.ts | 2 +- .../hermes/hermes-image-build-probes.test.ts | 3 +- .../hermes/hermes-runtime-api-key.test.ts | 4 +- .../hermes/hermes-tool-gateway-broker.test.ts | 4 +- .../openclaw-dependency-review.test.ts | 12 ++-- ...claw-gateway-daemon-dialback-patch.test.ts | 8 +-- ...nclaw-issue-4434-diagnostics-patch.test.ts | 4 +- .../openclaw/openclaw-mcp-npx-patch.test.ts | 2 +- .../openclaw-mcp-reliability-patch.test.ts | 4 +- .../openclaw-optional-plugin-build.test.ts | 2 +- ...openclaw-real-patched-dist-harness.test.ts | 16 ++--- ...law-shared-state-permissions-patch.test.ts | 2 +- .../openclaw-tool-catalog-patch.test.ts | 2 +- .../pi-candidate-runtime-artifacts.test.ts | 2 +- test/automation/classify-ci-failure.test.ts | 2 - test/automation/e2e/e2e-private-file.test.ts | 4 +- .../e2e/e2e-recommendations.test.ts | 2 +- .../analyze-ci-performance.test.ts | 2 +- .../advisor-http-dispatcher.test.ts | 2 +- .../analyze-pr-value-stream.test.ts | 4 +- .../hosted-runner-recovery-workflow.test.ts | 2 +- ...e-conflict-fixer-workflow-boundary.test.ts | 2 +- .../pr-review-advisor-local.test.ts | 6 +- .../pr-review-advisor-openshell.test.ts | 4 +- .../pr-review-advisor-specialists.test.ts | 2 +- .../pr-workflow-contract.test.ts | 2 +- .../releases/handoff-summary.test.ts | 2 +- .../releases/npm-audit-receipt.test.ts | 2 - .../releases/nvd-reconciliation.test.ts | 2 +- .../releases/release-latest-tag.test.ts | 12 +--- .../releases/retire-release-label.test.ts | 2 +- .../reviewed-npm-audit-entrypoint.test.ts | 1 - .../reviewed-npm-audit-handoff.test.ts | 2 - .../reviewed-npm-audit-workflow.test.ts | 1 - .../local-credential-helper-suite.ts | 1 - .../rebuild-credential-preflight.test.ts | 1 - test/e2e-runtime/candidate-compat.test.ts | 1 - test/e2e/e2e-cloud-experimental/check-docs.sh | 2 +- test/e2e/fixtures/fake-openai-compatible.ts | 2 +- test/e2e/lib/fake-discord-message-api.mts | 2 +- test/e2e/lib/fake-openai-compatible-api.mts | 2 +- test/e2e/lib/fake-wechat-api.mts | 2 +- test/e2e/lib/openai-compatible-api-proof.sh | 2 +- test/e2e/live/hermes-discord.test.ts | 1 - test/e2e/live/messaging-providers.test.ts | 1 - .../support/base-image-publication.test.ts | 1 - test/e2e/support/e2e-scorecard.test.ts | 2 +- .../hermes-langfuse-credential-patch.test.ts | 2 +- .../jetson-managed-revision-boundary.test.ts | 2 +- ...messaging-providers-runtime-proofs.test.ts | 2 +- ...e-qualification-collector-workflow.test.ts | 2 +- ...ay-auth-contract-workflow-boundary.test.ts | 4 +- ...hell-gateway-upgrade-old-installer.test.ts | 1 - .../support/podman-cpu-proof-workflow.test.ts | 7 +- .../pr-self-hosted-llama-selector.test.ts | 2 +- .../prepare-e2e-workflow-boundary.test.ts | 5 +- .../e2e/support/release-qualification.test.ts | 1 - test/e2e/support/runner-pressure.test.ts | 2 +- .../support/same-commit-reliability.test.ts | 2 +- .../generation/generate-hermes-config.test.ts | 2 +- ...te-managed-startup-profile-fixture.test.ts | 2 +- ...te-openclaw-config-agents-manifest.test.ts | 1 - .../generate-openclaw-config.test.ts | 4 +- test/helpers/historical-release-fixture.ts | 1 - ...claw-device-self-approval-patch-harness.ts | 2 +- ...penclaw-real-device-self-approval-proof.ts | 4 +- .../openclaw-real-mcp-start-retry-proof.ts | 4 +- .../llama/llama-cpp-image-workflow.test.ts | 2 +- test/inference/llama/llama-cpp-image.test.ts | 2 +- ...7-hosted-inference-model-namespace.test.ts | 1 - ...aller-homebrew-formula-reuse-trust.test.ts | 1 - .../installer-sandbox-build-trust.test.ts | 1 - ...nstaller-supervisor-manifest-trust.test.ts | 1 - .../update-hermes-agent-script.test.ts | 2 +- .../install-station-pair-preparation.test.ts | 2 - .../dashboard-remote-bind-lifecycle.test.ts | 24 +++---- .../openshell-policy-boundary.test.ts | 1 - ...race-expansion-dockerfile-contract.test.ts | 6 +- ...npm-ip-address-dockerfile-contract.test.ts | 8 +-- .../images/dockerfile-run-commands.test.ts | 4 +- .../node-tar-dockerfile-contract.test.ts | 4 +- ...otected-managed-image-build-script.test.ts | 6 +- .../repository/create-require-ratchet.test.ts | 2 +- .../shellcheck-json1-to-sarif.test.ts | 4 +- test/repository/stale-dist-check.test.ts | 2 +- ...aging-build-applier-credential-env.test.ts | 2 +- .../messaging-build-applier-integrity.test.ts | 2 - .../messaging/messaging-build-applier.test.ts | 6 +- .../fetch-guard-patch-regression.test.ts | 38 +++++----- test/security/mcporter-supply-chain.test.ts | 20 +++--- .../security-c2-dockerfile-injection.test.ts | 2 +- test/skills/check-gates-test-fixtures.ts | 1 - test/skills/triage-runtime.test.ts | 1 - ...openshell-gateway-auth-artifact-safety.mts | 2 +- ...ateway-auth-contract-workflow-boundary.mts | 2 +- tools/e2e/operations-workflow-boundary.mts | 16 ++--- tools/e2e/target-catalogue.mts | 2 +- tools/e2e/workflow-boundary.mts | 2 +- tools/mcp-tool-discovery-runtime/package.json | 8 +-- .../managed-startup-image-runtime.bundle | 2 +- tools/pr-review-advisor/local-review.mts | 2 +- tools/pr-review-advisor/openshell.mts | 2 - 205 files changed, 422 insertions(+), 484 deletions(-) diff --git a/.agents/skills/nemoclaw-maintainer-analyze-ci-performance/SKILL.md b/.agents/skills/nemoclaw-maintainer-analyze-ci-performance/SKILL.md index 70b7392c256..31fb208af8b 100644 --- a/.agents/skills/nemoclaw-maintainer-analyze-ci-performance/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-analyze-ci-performance/SKILL.md @@ -16,7 +16,7 @@ Run one read-only standalone analyzer from a NemoClaw checkout. Both commands us Use retained `cli-vitest-results` artifacts to rank consistently slow tests and files. The CI workflow retains this historical input for 14 days: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-analyze-ci-performance/scripts/analyze-recent-cli-timings.mts \ --workdir "$PWD" ``` @@ -30,7 +30,7 @@ The analyzer requires at least two usable retained reports. It rejects compresse Compare main-push E2E runs that publish a same-commit base image with runs that reuse a prior publication: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-analyze-ci-performance/scripts/analyze-base-image-publication-timings.mts \ --workdir "$PWD" ``` diff --git a/.agents/skills/nemoclaw-maintainer-analyze-pr-value-stream/SKILL.md b/.agents/skills/nemoclaw-maintainer-analyze-pr-value-stream/SKILL.md index 1834acd55bb..ed6057ed58c 100644 --- a/.agents/skills/nemoclaw-maintainer-analyze-pr-value-stream/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-analyze-pr-value-stream/SKILL.md @@ -22,7 +22,7 @@ Do not run a reduced or latest-revision-only analysis. The latest-revision water ## Run the analysis ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-analyze-pr-value-stream/scripts/analyze-pr-value-stream.mts \ --workdir "$PWD" \ --number diff --git a/.agents/skills/nemoclaw-maintainer-classify-ci-failure/SKILL.md b/.agents/skills/nemoclaw-maintainer-classify-ci-failure/SKILL.md index 1ee27802382..bd719544ec9 100644 --- a/.agents/skills/nemoclaw-maintainer-classify-ci-failure/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-classify-ci-failure/SKILL.md @@ -12,7 +12,7 @@ user_invocable: true Run the classifier from a NemoClaw checkout: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-classify-ci-failure/scripts/classify-ci-failure.mts \ --workdir "$PWD" --job-id ``` diff --git a/.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md b/.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md index 4bba53cc5d4..679295dc0cc 100644 --- a/.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-cut-release-tag/SKILL.md @@ -122,7 +122,7 @@ Create the brief template now, before collecting evidence, so each result can be read: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-day/scripts/handoff-summary.ts \ --plan ../nemoclaw-release-vX.Y.Z/plan.json \ --output ../nemoclaw-release-vX.Y.Z/release-brief.md diff --git a/.agents/skills/nemoclaw-maintainer-day/HOTSPOTS.md b/.agents/skills/nemoclaw-maintainer-day/HOTSPOTS.md index 1be98bf8e67..5dc05bc3c17 100644 --- a/.agents/skills/nemoclaw-maintainer-day/HOTSPOTS.md +++ b/.agents/skills/nemoclaw-maintainer-day/HOTSPOTS.md @@ -8,7 +8,7 @@ Find files that slow development and reduce future merge conflicts. ## Step 1: Run the Hotspot Script ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts ``` The script combines 30 days of `main` changes with file overlap from open PRs. @@ -17,7 +17,7 @@ It marks risky areas and returns a ranked JSON list. Pipe into state: ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts | node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts set-hotspots +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts | node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts set-hotspots ``` ## Step 2: Prioritize diff --git a/.agents/skills/nemoclaw-maintainer-day/SKILL.md b/.agents/skills/nemoclaw-maintainer-day/SKILL.md index 6354ac7a61e..c5ce55f7450 100644 --- a/.agents/skills/nemoclaw-maintainer-day/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-day/SKILL.md @@ -29,8 +29,8 @@ first. ## Step 1: Check Version Progress ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts ``` The first script selects the target version. The second lists shipped and open items. @@ -70,7 +70,7 @@ Follow the selected workflow. Complete one outcome in each pass: Re-run the progress script and show the update: ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts ``` If all items for the release version are done, suggest `/nemoclaw-maintainer-evening`. @@ -78,7 +78,7 @@ If all items for the release version are done, suggest `/nemoclaw-maintainer-eve Update `.nemoclaw-maintainer/state.json` via the state script: ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts history "" +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts history "" ``` ## Commit Hygiene diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts index 4a1e08ae4bd..037d8060723 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts @@ -7,7 +7,7 @@ * Checks all required gates and outputs structured JSON. * Claude uses the output to decide: approve, route to salvage, or report blockers. * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts [--repo OWNER/REPO] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts [--repo OWNER/REPO] */ import { isDeepStrictEqual } from "node:util"; diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/handoff-summary.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/handoff-summary.ts index 1da7f4f922f..d7d7300df0e 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/handoff-summary.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/handoff-summary.ts @@ -5,7 +5,7 @@ * Generate exact-range QA context for a release brief. * * Usage: - * node --experimental-strip-types --no-warnings handoff-summary.ts \ + * node --no-warnings handoff-summary.ts \ * --plan PATH --output PATH */ diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts index 111099d780e..d2ad1643de2 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts @@ -7,7 +7,7 @@ * Combines 30-day git churn on main with open PR file overlap to rank * the files causing the most merge pain. Outputs structured JSON. * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts [--days N] [--repo OWNER/REPO] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/hotspots.ts [--days N] [--repo OWNER/REPO] */ import { isRiskyFile, run, parseStringArg, parseIntArg } from "./shared.ts"; diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/run-trusted-check-gates.sh b/.agents/skills/nemoclaw-maintainer-day/scripts/run-trusted-check-gates.sh index a2e1197f33c..87030e92960 100755 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/run-trusted-check-gates.sh +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/run-trusted-check-gates.sh @@ -33,4 +33,4 @@ for file in "${surface[@]}"; do cmp -s "$trusted_root/$file" "$file" done test -z "$(git status --porcelain -- "${surface[@]}")" -node --experimental-strip-types --no-warnings "$trusted_root/$path" "$1" +node --no-warnings "$trusted_root/$path" "$1" diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/state.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/state.ts index 4675df3a6e3..051597f7dc0 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/state.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/state.ts @@ -13,7 +13,7 @@ * set-queue Update queue from triage output (pipe JSON to stdin) * set-hotspots Update hotspots from hotspot output (pipe JSON to stdin) * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts [args] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts [args] */ import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from "node:fs"; diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/triage.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/triage.ts index ecea9f9f489..1b19c73aebc 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/triage.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/triage.ts @@ -9,7 +9,7 @@ * scoring weights, filters exclusions from the state file, and outputs * a ranked JSON queue. * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts [--limit N] [--approved-only] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts [--limit N] [--approved-only] */ import { existsSync, readFileSync } from "node:fs"; diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts index 291e5334212..6ebeee6d0b4 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts @@ -4,7 +4,7 @@ /** * Check progress for a version label: shipped vs still open. * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts [--repo OWNER/REPO] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts [--repo OWNER/REPO] */ import { run, parseStringArg } from "./shared.ts"; diff --git a/.agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts b/.agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts index 84e97e6750b..8d9837c2d26 100644 --- a/.agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts +++ b/.agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts @@ -8,7 +8,7 @@ * queries GitHub for open PRs/issues carrying version labels older than * the target. Output is JSON. * - * Usage: node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts [--repo OWNER/REPO] + * Usage: node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts [--repo OWNER/REPO] */ import { run, parseStringArg } from "./shared.ts"; diff --git a/.agents/skills/nemoclaw-maintainer-evening/SKILL.md b/.agents/skills/nemoclaw-maintainer-evening/SKILL.md index 2a2e3cdd2b2..cf99cd73a81 100644 --- a/.agents/skills/nemoclaw-maintainer-evening/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-evening/SKILL.md @@ -22,9 +22,9 @@ Use the maintainer's `vX.Y.Z` when supplied. Otherwise, read the current target merged and open work: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-day/scripts/version-progress.ts vX.Y.Z ``` diff --git a/.agents/skills/nemoclaw-maintainer-fix-e2e-failures/scripts/run-trusted-policy.sh b/.agents/skills/nemoclaw-maintainer-fix-e2e-failures/scripts/run-trusted-policy.sh index ff32183e2eb..f1abe77b201 100755 --- a/.agents/skills/nemoclaw-maintainer-fix-e2e-failures/scripts/run-trusted-policy.sh +++ b/.agents/skills/nemoclaw-maintainer-fix-e2e-failures/scripts/run-trusted-policy.sh @@ -33,4 +33,4 @@ for file in "${surface[@]}"; do cmp -s "$trusted_root/$file" "$file" done test -z "$(git status --porcelain -- "${surface[@]}")" -node --experimental-strip-types "$trusted_root/$path" <"$1" +node "$trusted_root/$path" <"$1" diff --git a/.agents/skills/nemoclaw-maintainer-morning/SKILL.md b/.agents/skills/nemoclaw-maintainer-morning/SKILL.md index daaf4a6be86..372eaf202ea 100644 --- a/.agents/skills/nemoclaw-maintainer-morning/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-morning/SKILL.md @@ -13,7 +13,7 @@ See [PR-REVIEW-PRIORITIES.md](../nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md ## Step 1: Determine Target Version and Stragglers ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/version-target.ts ``` This fetches tags, computes the next patch version, and finds open items still carrying older version labels. Surface stragglers first — they indicate post-tag housekeeping was interrupted or an item slipped across multiple cycles. Decide whether to relabel them to today's target or defer them out of the daily release flow. @@ -23,7 +23,7 @@ This fetches tags, computes the next patch version, and finds open items still c Run the triage script to rank the full backlog: ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts --approved-only +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts --approved-only ``` If too few results, run without `--approved-only`. The script fetches open PRs through `gh`, reads Project 199 Priority, enriches candidates with review, CI, file, and risky-area data, and applies the scoring model documented in [PR-REVIEW-PRIORITIES.md](../nemoclaw-maintainer-day/PR-REVIEW-PRIORITIES.md). @@ -45,8 +45,8 @@ gh issue edit --repo NVIDIA/NemoClaw --add-label "" Pipe triage output into state: ```bash -node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts \ - | node --experimental-strip-types --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts set-queue +node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/triage.ts \ + | node --no-warnings .agents/skills/nemoclaw-maintainer-day/scripts/state.ts set-queue ``` Output the daily plan: diff --git a/.agents/skills/nemoclaw-maintainer-normalize-title-tags/SKILL.md b/.agents/skills/nemoclaw-maintainer-normalize-title-tags/SKILL.md index 576240f04f9..f55c3cb114c 100644 --- a/.agents/skills/nemoclaw-maintainer-normalize-title-tags/SKILL.md +++ b/.agents/skills/nemoclaw-maintainer-normalize-title-tags/SKILL.md @@ -44,7 +44,7 @@ gh auth status ## Step 2: Preview Proposed Changes ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts ``` @@ -64,7 +64,7 @@ Ask the user which scope they want: Apply to all items: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts \ --apply ``` @@ -72,7 +72,7 @@ node --experimental-strip-types --no-warnings \ Apply only to open items: ```bash -node --experimental-strip-types --no-warnings \ +node --no-warnings \ .agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts \ --state open \ --apply diff --git a/.agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts b/.agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts index af4ae9d9d7c..d73781dc500 100644 --- a/.agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts +++ b/.agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts @@ -8,7 +8,7 @@ * anywhere in the title. * * Usage: - * node --experimental-strip-types --no-warnings \ + * node --no-warnings \ * .agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts \ * [--repo OWNER/REPO] [--state all|open|closed] [--apply] */ @@ -53,7 +53,7 @@ const BRACKET_TAG_REGEX = /\[[^\]]+\]/g; function usage(): string { return [ "Usage:", - " node --experimental-strip-types --no-warnings \\", + " node --no-warnings \\", " .agents/skills/nemoclaw-maintainer-normalize-title-tags/scripts/normalize-title-tags.ts \\", " [--repo OWNER/REPO] [--state all|open|closed] [--apply]", "", diff --git a/.dsh/tools/refresh_locked_npm_cache_seed/index.ts b/.dsh/tools/refresh_locked_npm_cache_seed/index.ts index ca0dc5bcec6..803c3c477a5 100644 --- a/.dsh/tools/refresh_locked_npm_cache_seed/index.ts +++ b/.dsh/tools/refresh_locked_npm_cache_seed/index.ts @@ -107,7 +107,6 @@ export default async function refresh_locked_npm_cache_seed(input: { try { const generateCommand = [ "node", - "--experimental-strip-types", "--no-warnings", generator, "export", diff --git a/.github/actions/ci-compile-artifacts/action.yaml b/.github/actions/ci-compile-artifacts/action.yaml index 5aa86be0ff5..a9b08339417 100644 --- a/.github/actions/ci-compile-artifacts/action.yaml +++ b/.github/actions/ci-compile-artifacts/action.yaml @@ -19,7 +19,7 @@ runs: - name: Identify compiled output id: identity shell: bash - run: node --experimental-strip-types "$GITHUB_ACTION_PATH/compiled-artifact.mts" identity + run: node "$GITHUB_ACTION_PATH/compiled-artifact.mts" identity - name: Restore compiled CLI and plugin id: cache @@ -54,8 +54,8 @@ runs: shell: bash run: | set -euo pipefail - node --experimental-strip-types "$GITHUB_ACTION_PATH/compiled-artifact.mts" verify - node --experimental-strip-types "$GITHUB_ACTION_PATH/../../../scripts/check-dist-sourcemaps.mts" dist + node "$GITHUB_ACTION_PATH/compiled-artifact.mts" verify + node "$GITHUB_ACTION_PATH/../../../scripts/check-dist-sourcemaps.mts" dist - name: Save compiled CLI and plugin if: steps.cache.outputs.cache-hit != 'true' diff --git a/.github/actions/ci-install-dependencies.sh b/.github/actions/ci-install-dependencies.sh index d0748c5c37c..4d6480789c4 100755 --- a/.github/actions/ci-install-dependencies.sh +++ b/.github/actions/ci-install-dependencies.sh @@ -36,7 +36,7 @@ NEMOCLAW_CI_NPM_CACHE="$npm_cache" \ NEMOCLAW_CI_NPM_PACKAGE_MODE="$package_mode" \ NEMOCLAW_CI_TARGET_ROOT="$target_root" \ NEMOCLAW_OPEN_SHELL_SDK_ARTIFACT_DIRECTORY="${RUNNER_TEMP:-$target_root/.ci-artifacts}/openshell-sdk" \ - node --experimental-strip-types "$trusted_root/scripts/checks/prepare-ci-npm-install.mts" + node "$trusted_root/scripts/checks/prepare-ci-npm-install.mts" trusted_npmrc="" cleanup() { diff --git a/.github/actions/ci-reviewed-npm-audit/action.yaml b/.github/actions/ci-reviewed-npm-audit/action.yaml index c70ce662068..c67dad6177d 100644 --- a/.github/actions/ci-reviewed-npm-audit/action.yaml +++ b/.github/actions/ci-reviewed-npm-audit/action.yaml @@ -37,7 +37,7 @@ runs: set -euo pipefail current_bucket="$(( $(date -u +%s) / 43200 ))" previous_bucket="$(( current_bucket - 1 ))" - node --experimental-strip-types --input-type=module - \ + node --input-type=module - \ "$GITHUB_ACTION_PATH/../../../ci/reviewed-npm-audit.json" \ "$GITHUB_ACTION_PATH/../../../scripts/lib/repository-input-path.mts" <<'NODE' import { createHash } from "node:crypto"; @@ -106,7 +106,7 @@ runs: NEMOCLAW_REVIEWED_NPM_AUDIT_CACHE_DIR: ${{ inputs.cache-directory }} NPM_CONFIG_REGISTRY: https://registry.npmjs.org/ NPM_CONFIG_USERCONFIG: /dev/null - run: env -u NODE_AUTH_TOKEN -u NPM_TOKEN -u NPM_CONFIG__AUTH_TOKEN node --experimental-strip-types "$GITHUB_ACTION_PATH/../../../scripts/audit-reviewed-npm-graph.mts" + run: env -u NODE_AUTH_TOKEN -u NPM_TOKEN -u NPM_CONFIG__AUTH_TOKEN node "$GITHUB_ACTION_PATH/../../../scripts/audit-reviewed-npm-graph.mts" - name: Save current reviewed npm audit cache bucket if: inputs.trusted-cache-write == 'true' && steps.cache-current.outputs.cache-hit != 'true' diff --git a/.github/actions/ci-static-checks/action.yaml b/.github/actions/ci-static-checks/action.yaml index 6ae0a731265..5f3f984640b 100644 --- a/.github/actions/ci-static-checks/action.yaml +++ b/.github/actions/ci-static-checks/action.yaml @@ -22,7 +22,7 @@ runs: - name: Enforce base-trusted createRequire allowlist ratchet shell: bash - run: node --experimental-strip-types "$GITHUB_ACTION_PATH/create-require-ratchet.mts" + run: node "$GITHUB_ACTION_PATH/create-require-ratchet.mts" - name: Install hadolint shell: bash diff --git a/.github/workflows/candidate-compatibility.yaml b/.github/workflows/candidate-compatibility.yaml index e820f6d0263..3f13d33ac5e 100644 --- a/.github/workflows/candidate-compatibility.yaml +++ b/.github/workflows/candidate-compatibility.yaml @@ -73,7 +73,7 @@ jobs: nemoclaw_sha="$(git -C candidate-source rev-parse --verify HEAD^{commit})" [[ "$nemoclaw_sha" =~ ^[a-f0-9]{40}$ ]] || { echo "::error::NemoClaw ref did not resolve to a full commit SHA"; exit 1; } [[ -z "$(git -C candidate-source status --short --untracked-files=no)" ]] || { echo "::error::checkout is not clean before candidate resolution"; exit 1; } - node --experimental-strip-types controller/tools/candidate-compat.mts resolve \ + node controller/tools/candidate-compat.mts resolve \ --nemoclaw-sha "$nemoclaw_sha" \ --component "$COMPONENT" \ --candidate "$CANDIDATE" \ @@ -89,7 +89,7 @@ jobs: shell: bash run: | set -euo pipefail - node --experimental-strip-types controller/tools/candidate-compat.mts plan \ + node controller/tools/candidate-compat.mts plan \ --component "$COMPONENT" \ --e2e-workflow candidate-source/.github/workflows/e2e.yaml \ --e2e-registry candidate-source/test/e2e/registry/definitions/baseline.ts \ @@ -165,7 +165,7 @@ jobs: shell: bash run: | set -euo pipefail - node --experimental-strip-types controller/tools/candidate-compat.mts materialize \ + node controller/tools/candidate-compat.mts materialize \ --receipt candidate-input/candidate-receipt.json \ --resolution-id "$RESOLUTION_ID" \ --directory "${RUNNER_TEMP}/candidate-runtime" \ @@ -212,7 +212,7 @@ jobs: set -euo pipefail mkdir -p candidate-results if [[ "$CANDIDATE_OUTCOME" == success && "$LANE_OUTCOME" == success ]]; then - node --experimental-strip-types controller/tools/candidate-compat.mts verify-invocations \ + node controller/tools/candidate-compat.mts verify-invocations \ --receipt candidate-input/candidate-receipt.json \ --resolution-id "$RESOLUTION_ID" \ --log "$NEMOCLAW_CANDIDATE_INVOCATION_LOG" \ @@ -291,7 +291,7 @@ jobs: RESOLUTION_ID: ${{ needs.resolve.outputs.resolution_id }} run: | set -euo pipefail - node --experimental-strip-types controller/tools/candidate-compat.mts materialize \ + node controller/tools/candidate-compat.mts materialize \ --receipt candidate-input/candidate-receipt.json \ --resolution-id "$RESOLUTION_ID" \ --directory "${RUNNER_TEMP}/candidate-runtime" \ @@ -331,7 +331,7 @@ jobs: mkdir -p candidate-results lane=live:openshell-gateway-auth-contract if [[ "$CANDIDATE_OUTCOME" == success && "$LANE_OUTCOME" == success ]]; then - node --experimental-strip-types controller/tools/candidate-compat.mts verify-invocations \ + node controller/tools/candidate-compat.mts verify-invocations \ --receipt candidate-input/candidate-receipt.json \ --resolution-id "$RESOLUTION_ID" \ --log "$NEMOCLAW_CANDIDATE_INVOCATION_LOG" \ @@ -353,7 +353,7 @@ jobs: if: ${{ always() }} env: E2E_ARTIFACT_DIR: ${{ github.workspace }}/candidate-source/e2e-artifacts/live/openshell-gateway-auth-contract - run: node --experimental-strip-types --no-warnings controller/tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR" + run: node --no-warnings controller/tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR" - name: Upload live evidence if: ${{ always() }} @@ -415,7 +415,7 @@ jobs: shell: bash run: | set -euo pipefail - node --experimental-strip-types controller/tools/candidate-compat.mts finalize \ + node controller/tools/candidate-compat.mts finalize \ --receipt candidate-input/candidate-receipt.json \ --resolution-id "$RESOLUTION_ID" \ --plan candidate-input/candidate-plan.json \ diff --git a/.github/workflows/code-scanning.yaml b/.github/workflows/code-scanning.yaml index 62514677e53..43b3b301af6 100644 --- a/.github/workflows/code-scanning.yaml +++ b/.github/workflows/code-scanning.yaml @@ -140,7 +140,7 @@ jobs: esac conversion_exit=0 - if env -i PATH="$PATH" node --experimental-strip-types \ + if env -i PATH="$PATH" node \ "$GITHUB_WORKSPACE/trusted-shellcheck-converter/scripts/shellcheck-json1-to-sarif.mts" \ "$GITHUB_WORKSPACE/shellcheck.json" "$GITHUB_WORKSPACE/shellcheck.sarif"; then conversion_exit=0 diff --git a/.github/workflows/e2e-main-retry.yaml b/.github/workflows/e2e-main-retry.yaml index c37339a6ae0..2667ad60c45 100644 --- a/.github/workflows/e2e-main-retry.yaml +++ b/.github/workflows/e2e-main-retry.yaml @@ -55,7 +55,7 @@ jobs: RETRY_EVIDENCE_PATH: ${{ runner.temp }}/e2e-main-retry-evidence.json SOURCE_RUN_ID: ${{ github.event.workflow_run.id }} run: >- - node --experimental-strip-types --no-warnings + node --no-warnings tools/e2e/main-run-retry.mts - name: Upload retry evidence @@ -105,7 +105,7 @@ jobs: shell: bash run: | set -euo pipefail - node --experimental-strip-types --no-warnings \ + node --no-warnings \ tools/e2e/same-commit-reliability.mts \ >"${RUNNER_TEMP}/same-commit-reliability.json" \ 2>"${RUNNER_TEMP}/same-commit-reliability.md" diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index b5c77f3ff8b..4d5846ddee8 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -154,7 +154,7 @@ jobs: NODE_AUTH_TOKEN: ${{ github.token }} run: | set -euo pipefail - artifact_path="$(node --experimental-strip-types scripts/checks/package-openshell-sdk-for-pr.mts)" + artifact_path="$(node scripts/checks/package-openshell-sdk-for-pr.mts)" test -n "$artifact_path" printf 'artifact_path=%s\n' "$artifact_path" >> "$GITHUB_OUTPUT" @@ -264,7 +264,7 @@ jobs: exit 1 } fi - selection="$(node --experimental-strip-types --no-warnings tools/e2e/pr-managed-image-publication.mts "$catalog_path")" + selection="$(node --no-warnings tools/e2e/pr-managed-image-publication.mts "$catalog_path")" case "$selection" in base-cohort) [[ ! -e "$catalog_path" && ! -L "$catalog_path" ]] || { @@ -307,7 +307,7 @@ jobs: if [[ "$SELECT_NEAREST_SUCCESSFUL_PUBLICATION" == "1" ]]; then wait_seconds=300 fi - node --experimental-strip-types --no-warnings tools/e2e/base-image-publication.mts --wait-seconds "$wait_seconds" --poll-seconds 30 + node --no-warnings tools/e2e/base-image-publication.mts --wait-seconds "$wait_seconds" --poll-seconds 30 - name: Download immutable Deep Agents Code base contract if: ${{ inputs.pr_number == '' || steps.select_pr_source.outputs.selection == 'base-cohort' || inputs.jobs != '' || inputs.targets == '' || contains(inputs.targets, 'managed-image-') }} @@ -316,7 +316,7 @@ jobs: PUBLICATION_HEAD_SHA: ${{ steps.publication.outputs.head_sha }} PUBLICATION_RUN_ATTEMPT: ${{ steps.publication.outputs.run_attempt }} PUBLICATION_RUN_ID: ${{ steps.publication.outputs.run_id }} - run: node --experimental-strip-types --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/dcode-base-contract" + run: node --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/dcode-base-contract" - id: validate_dcode_base name: Validate immutable Deep Agents Code base @@ -325,7 +325,7 @@ jobs: PUBLICATION_HEAD_SHA: ${{ steps.publication.outputs.head_sha }} PUBLICATION_RUN_ATTEMPT: ${{ steps.publication.outputs.run_attempt }} PUBLICATION_RUN_ID: ${{ steps.publication.outputs.run_id }} - run: node --experimental-strip-types --no-warnings tools/e2e/dcode-base-image-contract.mts "${RUNNER_TEMP}/dcode-base-contract/contract.json" + run: node --no-warnings tools/e2e/dcode-base-image-contract.mts "${RUNNER_TEMP}/dcode-base-contract/contract.json" - id: download_managed_cohort name: Download immutable managed-image cohort contract @@ -336,7 +336,7 @@ jobs: PUBLICATION_HEAD_SHA: ${{ steps.publication.outputs.head_sha }} PUBLICATION_RUN_ATTEMPT: ${{ steps.publication.outputs.run_attempt }} PUBLICATION_RUN_ID: ${{ steps.publication.outputs.run_id }} - run: node --experimental-strip-types --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/managed-image-cohort" + run: node --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/managed-image-cohort" - id: validate_managed_cohort name: Validate immutable managed-image cohort contract @@ -345,7 +345,7 @@ jobs: PUBLICATION_HEAD_SHA: ${{ steps.publication.outputs.head_sha }} PUBLICATION_RUN_ATTEMPT: ${{ steps.publication.outputs.run_attempt }} PUBLICATION_RUN_ID: ${{ steps.publication.outputs.run_id }} - run: node --experimental-strip-types --no-warnings tools/e2e/managed-image-cohort-contract.mts "${RUNNER_TEMP}/managed-image-cohort/cohort.json" + run: node --no-warnings tools/e2e/managed-image-cohort-contract.mts "${RUNNER_TEMP}/managed-image-cohort/cohort.json" generate-matrix: needs: base-image-publication @@ -1010,7 +1010,7 @@ jobs: PRODUCER_RUN_ATTEMPT: ${{ github.run_attempt }} PRODUCER_RUN_ID: ${{ github.run_id }} WORKFLOW_SHA: ${{ github.workflow_sha }} - run: node --experimental-strip-types --no-warnings tools/e2e/native-runtime-qualification-producer-plan.mts --ci-output + run: node --no-warnings tools/e2e/native-runtime-qualification-producer-plan.mts --ci-output native-runtime-qualification-podman-toolchain: name: Build pinned native Podman toolchain / ${{ matrix.architecture }} @@ -2170,7 +2170,7 @@ jobs: run: | set -euo pipefail sudo --preserve-env=EVIDENCE_DIRECTORY,EXECUTION_RECEIPT_PATH,INSTALLER_RECEIPT_DIRECTORY,QUALIFICATION_ROW \ - "$NODE_DIRECTORY/node" --experimental-strip-types --no-warnings \ + "$NODE_DIRECTORY/node" --no-warnings \ .qualification-workflow/tools/e2e/native-runtime-qualification-producer-evidence.mts sudo chown -R "$(id -u):$(id -g)" "$EVIDENCE_DIRECTORY" @@ -2528,7 +2528,7 @@ jobs: EVIDENCE_DIRECTORY: ${{ runner.temp }}/native-runtime-aggregate QUALIFICATION_PLAN: ${{ needs.native-runtime-qualification-producer-plan.outputs.matrix }} run: >- - node --experimental-strip-types --no-warnings tools/e2e/native-runtime-qualification-producer-aggregate.mts + node --no-warnings tools/e2e/native-runtime-qualification-producer-aggregate.mts - name: Upload aggregate evidence uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 @@ -3353,7 +3353,7 @@ jobs: - id: artifact_safety name: Validate final OpenShell gateway auth contract artifacts if: always() - run: node --experimental-strip-types --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR" + run: node --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR" - name: Upload OpenShell gateway auth contract artifacts if: ${{ always() && steps.artifact_safety.outcome == 'success' && steps.artifact_safety.outputs.approved_path != '' }} @@ -3971,7 +3971,7 @@ jobs: - id: resolve_openshell_dev_artifact name: Resolve immutable OpenShell dev artifact run: >- - node --experimental-strip-types --no-warnings "${{ github.workspace }}/.trusted-openshell-dev-artifact/tools/e2e/openshell-dev-artifact.mts" resolve "${{ runner.temp }}/openshell-dev-artifact" + node --no-warnings "${{ github.workspace }}/.trusted-openshell-dev-artifact/tools/e2e/openshell-dev-artifact.mts" resolve "${{ runner.temp }}/openshell-dev-artifact" - name: Upload OpenShell dev artifact resolution if: ${{ always() }} @@ -4064,7 +4064,7 @@ jobs: OPENSHELL_DEV_EXPECTED_MANIFEST_SHA256: ${{ needs.openshell-dev-artifact.outputs.manifest_sha256 }} OPENSHELL_DEV_EXPECTED_SOURCE_COMMIT: ${{ needs.openshell-dev-artifact.outputs.source_commit }} run: >- - node --experimental-strip-types --no-warnings "${{ github.workspace }}/.trusted-openshell-dev-artifact/tools/e2e/openshell-dev-artifact.mts" verify "$OPENSHELL_DEV_ARTIFACT_DIR" "$OPENSHELL_DEV_EXPECTED_SOURCE_COMMIT" "$OPENSHELL_DEV_EXPECTED_MANIFEST_SHA256" + node --no-warnings "${{ github.workspace }}/.trusted-openshell-dev-artifact/tools/e2e/openshell-dev-artifact.mts" verify "$OPENSHELL_DEV_ARTIFACT_DIR" "$OPENSHELL_DEV_EXPECTED_SOURCE_COMMIT" "$OPENSHELL_DEV_EXPECTED_MANIFEST_SHA256" - name: Revoke Docker auth before OpenShell development tooling shell: bash @@ -4732,7 +4732,7 @@ jobs: echo "::error::Protected llama.cpp candidate checkout does not match the candidate SHA" >&2 exit 1 } - node --experimental-strip-types --no-warnings \ + node --no-warnings \ scripts/checks/export-llama-cpp-dgx-spark-qualification-plan.mts \ --source-root "$CANDIDATE_ROOT" @@ -5676,7 +5676,7 @@ jobs: JETSON_DISPATCH_CANDIDATE_SHA: ${{ inputs.checkout_sha || github.sha }} JETSON_DISPATCH_MANAGED_IMAGE_REVISION: ${{ needs.base-image-publication.outputs.managed_image_revision }} JETSON_DISPATCH_URL: ${{ vars.JETSON_DISPATCH_URL }} - run: node --experimental-strip-types --no-warnings tools/e2e/jetson-dispatch-client.mts + run: node --no-warnings tools/e2e/jetson-dispatch-client.mts - name: Upload Jetson nvmap GPU artifacts if: always() @@ -6135,7 +6135,7 @@ jobs: env: NEEDS_JSON: ${{ toJSON(needs) }} RELEASE_REQUIRED_JOBS: ${{ needs.generate-matrix.outputs.selected_workflow_jobs }} - run: node --experimental-strip-types --no-warnings tools/e2e/release-qualification.mts + run: node --no-warnings tools/e2e/release-qualification.mts - name: Summarize selected E2E env: SELECTED_WORKFLOW_JOBS: ${{ needs.generate-matrix.outputs.selected_workflow_jobs }} @@ -6171,7 +6171,7 @@ jobs: env: NEEDS_JSON: ${{ toJSON(needs) }} RELEASE_REQUIRED_JOBS: ${{ needs.generate-matrix.outputs.release_required_jobs }} - run: node --experimental-strip-types --no-warnings tools/e2e/release-qualification.mts + run: node --no-warnings tools/e2e/release-qualification.mts # ── Push/manual scorecard ───────────────────────────────────────────────── scorecard: diff --git a/.github/workflows/hosted-runner-recovery.yaml b/.github/workflows/hosted-runner-recovery.yaml index 887b73fd1dc..785559dc385 100644 --- a/.github/workflows/hosted-runner-recovery.yaml +++ b/.github/workflows/hosted-runner-recovery.yaml @@ -54,7 +54,7 @@ jobs: GITHUB_TOKEN: ${{ github.token }} SOURCE_RUN_ID: ${{ github.event.workflow_run.id }} run: >- - node --experimental-strip-types --no-warnings + node --no-warnings tools/e2e/hosted-runner-recovery.mts - name: Record static recovery policy diff --git a/.github/workflows/llama-cpp-image.yaml b/.github/workflows/llama-cpp-image.yaml index 804d38d38f8..c3abab48b88 100644 --- a/.github/workflows/llama-cpp-image.yaml +++ b/.github/workflows/llama-cpp-image.yaml @@ -86,7 +86,7 @@ jobs: - name: Compile image manifest id: manifest - run: node --experimental-strip-types --no-warnings scripts/checks/export-llama-cpp-image-config.mts + run: node --no-warnings scripts/checks/export-llama-cpp-image-config.mts pr-build: name: Build native llama.cpp server (${{ matrix.arch }}) diff --git a/.github/workflows/managed-images.yaml b/.github/workflows/managed-images.yaml index aebdea56e62..a6da688e13e 100644 --- a/.github/workflows/managed-images.yaml +++ b/.github/workflows/managed-images.yaml @@ -1010,7 +1010,7 @@ jobs: mapfile -d '' contracts < <( find "$RUNNER_TEMP/managed-pr-contracts" -type f -name contract.json -print0 ) - node --experimental-strip-types --no-warnings \ + node --no-warnings \ tools/e2e/pr-managed-image-publication.mts assemble \ "$CANDIDATE_SHA" \ "$NEMOCLAW_MANAGED_ACTIVATION_CATALOG" \ @@ -1112,7 +1112,7 @@ jobs: mapfile -d '' contracts < <( find "$RUNNER_TEMP/managed-pr-contracts" -type f -name contract.json -print0 ) - node --experimental-strip-types --no-warnings \ + node --no-warnings \ tools/e2e/pr-managed-image-publication.mts assemble \ "$CANDIDATE_SHA" \ "$NEMOCLAW_E2E_MANAGED_IMAGE_CATALOG" \ @@ -1557,7 +1557,7 @@ jobs: startupProfileContractVersion: 1, capabilityContractVersion: 1 }' > "$contract_dir/contract.json" - node --experimental-strip-types tools/managed-images/validate-candidate-contract.mts \ + node tools/managed-images/validate-candidate-contract.mts \ --contract "$contract_dir/contract.json" \ --platform "$PLATFORM" # The all-agent activation job downloads managed-pr-contract-* artifacts. diff --git a/.github/workflows/native-runtime-qualification-collector.yaml b/.github/workflows/native-runtime-qualification-collector.yaml index 58fe53cdb43..de02ae4b8e4 100644 --- a/.github/workflows/native-runtime-qualification-collector.yaml +++ b/.github/workflows/native-runtime-qualification-collector.yaml @@ -89,7 +89,7 @@ jobs: EVIDENCE_ARTIFACT_NAME: ${{ inputs.evidence_artifact_name }} QUALIFICATION_AUTHORITY_PATH: ${{ runner.temp }}/native-runtime-qualification-authority.json run: >- - node --experimental-strip-types --no-warnings + node --no-warnings tools/e2e/native-runtime-qualification-collector.mts - name: Preserve authenticated authority receipt diff --git a/.github/workflows/openshell-sdk-package-pr.yaml b/.github/workflows/openshell-sdk-package-pr.yaml index 192571b510a..d47416178ee 100644 --- a/.github/workflows/openshell-sdk-package-pr.yaml +++ b/.github/workflows/openshell-sdk-package-pr.yaml @@ -58,7 +58,7 @@ jobs: NODE_AUTH_TOKEN: ${{ github.token }} run: | set -euo pipefail - artifact_path="$(node --experimental-strip-types scripts/checks/package-openshell-sdk-for-pr.mts)" + artifact_path="$(node scripts/checks/package-openshell-sdk-for-pr.mts)" [ -n "$artifact_path" ] printf 'artifact_path=%s\n' "$artifact_path" >> "$GITHUB_OUTPUT" diff --git a/.github/workflows/podman-cpu-proof.yaml b/.github/workflows/podman-cpu-proof.yaml index 817138b653e..7f22cdab62a 100644 --- a/.github/workflows/podman-cpu-proof.yaml +++ b/.github/workflows/podman-cpu-proof.yaml @@ -83,25 +83,25 @@ jobs: - name: Prepare system and app slice CPU settings without service delegation shell: bash - run: node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts prepare + run: node scripts/checks/run-portable-cpu-delegation-proof.mts prepare - name: Verify missing delegation blocks portable configuration and service activation shell: bash - run: node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts reject + run: node scripts/checks/run-portable-cpu-delegation-proof.mts reject - name: Apply administrator delegation and prove admission shell: bash - run: node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts admit + run: node scripts/checks/run-portable-cpu-delegation-proof.mts admit - name: Capture CPU delegation failure diagnostics if: failure() shell: bash - run: node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts diagnostics + run: node scripts/checks/run-portable-cpu-delegation-proof.mts diagnostics - name: Restore the user manager boundary if: always() shell: bash - run: node --experimental-strip-types scripts/checks/run-portable-cpu-delegation-proof.mts cleanup + run: node scripts/checks/run-portable-cpu-delegation-proof.mts cleanup - name: Upload CPU delegation evidence if: always() diff --git a/.github/workflows/portable-profile-e2e.yaml b/.github/workflows/portable-profile-e2e.yaml index faedad1e7bc..dc07c6a87de 100644 --- a/.github/workflows/portable-profile-e2e.yaml +++ b/.github/workflows/portable-profile-e2e.yaml @@ -329,7 +329,7 @@ jobs: /usr/bin/systemctl --user start podman.socket /usr/bin/systemctl --user is-active --quiet podman.socket - node --experimental-strip-types --no-warnings --input-type=module --eval ' + node --no-warnings --input-type=module --eval ' const { inspectPortableCpuDelegation } = await import( "./src/lib/onboard/experimental/portable-cpu-delegation-preflight.ts" ); diff --git a/.github/workflows/post-merge-docs.yaml b/.github/workflows/post-merge-docs.yaml index bf23276c49c..f655c110d5e 100644 --- a/.github/workflows/post-merge-docs.yaml +++ b/.github/workflows/post-merge-docs.yaml @@ -96,7 +96,7 @@ jobs: - name: Configure isolated inference env: OPENAI_API_KEY: ${{ secrets.POST_MERGE_DOCS_API_KEY }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" configure + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" configure - name: Author the documentation env: @@ -104,7 +104,7 @@ jobs: POST_MERGE_DOCS_PHASE: author POST_MERGE_DOCS_WORKDIR: ${{ github.workspace }}/author SANDBOX_NAME: docs-main-author - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" execute + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" execute - name: Validate the documentation candidate working-directory: author/repo @@ -124,7 +124,7 @@ jobs: POST_MERGE_DOCS_PHASE: review POST_MERGE_DOCS_WORKDIR: ${{ github.workspace }}/review SANDBOX_NAME: docs-main-review - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" execute + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/run.mts" execute - name: Explain failed independent review if: ${{ failure() && steps.review.outcome == 'failure' }} @@ -181,4 +181,4 @@ jobs: - name: Publish the reviewed patch env: GITHUB_TOKEN: ${{ github.token }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/publish.mts" + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/post-merge-docs/publish.mts" diff --git a/.github/workflows/pr-merge-conflict-fixer.yaml b/.github/workflows/pr-merge-conflict-fixer.yaml index 3d3c384cad4..72d29f0f7f5 100644 --- a/.github/workflows/pr-merge-conflict-fixer.yaml +++ b/.github/workflows/pr-merge-conflict-fixer.yaml @@ -39,7 +39,7 @@ jobs: name: Reproduce PR merges env: GITHUB_TOKEN: ${{ github.token }} - run: node --experimental-strip-types --no-warnings tools/pr-merge-conflict-fixer/discover.mts + run: node --no-warnings tools/pr-merge-conflict-fixer/discover.mts resolve: name: "Resolve PR #${{ matrix.item.pr_number }}" @@ -78,7 +78,7 @@ jobs: name: Reproduce the recorded conflict env: MATRIX_ENTRY: ${{ toJSON(matrix.item) }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" prepare + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" prepare - name: Install OpenShell run: | @@ -89,22 +89,22 @@ jobs: - name: Configure OpenShell inference env: OPENAI_API_KEY: ${{ secrets.PR_REVIEW_ADVISOR_API_KEY }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" configure + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" configure - name: Create the credential-free sandbox - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" create + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" create - name: Run one Pi conflict-resolution task - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" run + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" run - name: Export the Git patch env: CONFLICT_TREE: ${{ steps.prepare.outputs.conflict_tree }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" export + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" export - name: Delete the sandbox if: always() - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" delete + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" delete - name: Upload the resolution patch if: success() @@ -166,4 +166,4 @@ jobs: env: GITHUB_TOKEN: ${{ github.token }} MATRIX_ENTRY: ${{ toJSON(matrix.item) }} - run: node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/publish.mts" + run: node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/publish.mts" diff --git a/.github/workflows/pr-review-advisor.yaml b/.github/workflows/pr-review-advisor.yaml index 68bc08c23f3..709f888861d 100644 --- a/.github/workflows/pr-review-advisor.yaml +++ b/.github/workflows/pr-review-advisor.yaml @@ -124,11 +124,11 @@ jobs: submodules: false - name: Read specialist prompts id: specialists - run: node --experimental-strip-types tools/pr-review-advisor/render-specialist-matrix.mts + run: node tools/pr-review-advisor/render-specialist-matrix.mts - name: Collect GitHub review context env: GH_TOKEN: ${{ github.token }} - run: node --experimental-strip-types --no-warnings tools/pr-review-advisor/github-context.mts + run: node --no-warnings tools/pr-review-advisor/github-context.mts - name: Upload GitHub review context uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: @@ -275,7 +275,7 @@ jobs: cache-dependency-path: advisor/package-lock.json - name: Load advisor runtime image - run: node --experimental-strip-types --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/export-runtime-env.mts" + run: node --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/export-runtime-env.mts" # The source PR is fetched manually so no PR-controlled # action, hook, submodule, LFS filter, or package setup can run. The base @@ -293,7 +293,7 @@ jobs: GIT_LFS_SKIP_SMUDGE: "1" TARGET_DIR: ${{ github.workspace }}/pr-workdir run: | - node --experimental-strip-types \ + node \ "$ADVISOR_DIR/tools/pr-review-advisor/prepare-target-pr.mts" # symlinks first so an untrusted link cannot redirect a read outside the @@ -329,7 +329,7 @@ jobs: BASE_REF: ${{ github.event_name == 'workflow_run' && 'target/base' || (github.event_name == 'workflow_dispatch' && inputs.target_repo != '' && inputs.target_pr != '' && 'target/base' || inputs.base_ref) }} HEAD_REF: ${{ github.event_name == 'workflow_run' && 'HEAD' || (github.event_name == 'workflow_dispatch' && inputs.target_repo != '' && inputs.target_pr != '' && 'HEAD' || inputs.head_ref) }} PR_REVIEW_ADVISOR_GITHUB_CONTEXT_PATH: ${{ runner.temp }}/shared-pr-review-advisor-context/github-context.json - run: node --experimental-strip-types --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/specialist-lifecycle.mts" prepare + run: node --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/specialist-lifecycle.mts" prepare # Shared lifecycle phases preserve the configure-only credential boundary. - name: Install OpenShell @@ -342,7 +342,7 @@ jobs: id: specialist-analysis env: OPENAI_API_KEY: ${{ secrets.PR_REVIEW_ADVISOR_API_KEY }} - run: node --experimental-strip-types --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/specialist-lifecycle.mts" analysis + run: node --no-warnings "$ADVISOR_DIR/tools/pr-review-advisor/specialist-lifecycle.mts" analysis - name: Upload specialist review id: upload-specialist-session @@ -407,7 +407,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - node --experimental-strip-types "$ADVISOR_DIR/tools/pr-review-advisor/completion-comment.mts" \ + node "$ADVISOR_DIR/tools/pr-review-advisor/completion-comment.mts" \ --repo "$GITHUB_REPOSITORY" \ --pr "$PR_NUMBER" \ --marker "$PR_REVIEW_ADVISOR_COMMENT_MARKER" diff --git a/.github/workflows/pr-self-hosted.yaml b/.github/workflows/pr-self-hosted.yaml index 082b61a2cd7..be99af968cd 100644 --- a/.github/workflows/pr-self-hosted.yaml +++ b/.github/workflows/pr-self-hosted.yaml @@ -127,7 +127,7 @@ jobs: set -euo pipefail export GITHUB_REF=refs/heads/main export GITHUB_SHA="$EXPECTED_SHA" - node --experimental-strip-types --no-warnings tools/e2e/base-image-publication.mts --wait-seconds 3000 --poll-seconds 30 + node --no-warnings tools/e2e/base-image-publication.mts --wait-seconds 3000 --poll-seconds 30 llama-cpp-generic-gpu: name: llama.cpp on generic NVIDIA GPU diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index 2ea7172a64f..f7e1488c12e 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -243,7 +243,7 @@ jobs: decision="$( NEMOCLAW_CI_NPM_PACKAGE_MODE=inspect \ NEMOCLAW_CI_TARGET_ROOT="$GITHUB_WORKSPACE" \ - node --experimental-strip-types "$trusted_inspector" + node "$trusted_inspector" )" required="$( jq -ser ' diff --git a/.github/workflows/release-latest-tag.yaml b/.github/workflows/release-latest-tag.yaml index b85720253f9..031b2161514 100644 --- a/.github/workflows/release-latest-tag.yaml +++ b/.github/workflows/release-latest-tag.yaml @@ -103,5 +103,5 @@ jobs: GH_TOKEN: ${{ github.token }} RELEASE_TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }} run: >- - node --experimental-strip-types --no-warnings scripts/retire-release-label.mts + node --no-warnings scripts/retire-release-label.mts "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" diff --git a/.github/workflows/sandbox-images.yaml b/.github/workflows/sandbox-images.yaml index ae64e73a733..bda4c84a695 100644 --- a/.github/workflows/sandbox-images.yaml +++ b/.github/workflows/sandbox-images.yaml @@ -352,14 +352,14 @@ jobs: shell: bash run: | set -euo pipefail - messaging_plan_b64="$(node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts plan openclaw)" + messaging_plan_b64="$(node scripts/check-messaging-plan-image-boundary.mts plan openclaw)" build_args=( --build-arg "BASE_IMAGE=${BASE_IMAGE}" --build-arg "NEMOCLAW_MESSAGING_PLAN_B64=${messaging_plan_b64}" ) scripts/check-production-build-args.sh "${build_args[@]}" docker build "${build_args[@]}" -t nemoclaw-openclaw-plan-boundary . - node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts verify \ + node scripts/check-messaging-plan-image-boundary.mts verify \ nemoclaw-openclaw-plan-boundary openclaw - *hermes-export-swap @@ -373,11 +373,11 @@ jobs: # curl and Python replace their default roots with this build argument. compact_ca_bundle="$(mktemp)" trap 'rm -f "$compact_ca_bundle"' EXIT - node --experimental-strip-types scripts/checks/select-ci-endpoint-ca-roots.mts \ + node scripts/checks/select-ci-endpoint-ca-roots.mts \ --output "$compact_ca_bundle" corporate_ca_b64="$(base64 -w 0 "$compact_ca_bundle")" corporate_ca_sha256="$(sha256sum "$compact_ca_bundle" | cut -d ' ' -f 1)" - messaging_plan_b64="$(node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts plan hermes)" + messaging_plan_b64="$(node scripts/check-messaging-plan-image-boundary.mts plan hermes)" build_args=( -f agents/hermes/Dockerfile --build-arg "BASE_IMAGE=${HERMES_BASE_IMAGE}" @@ -396,7 +396,7 @@ jobs: docker run --rm --network none --entrypoint openssl \ nemoclaw-hermes-plan-boundary crl2pkcs7 -nocrl \ -certfile /usr/local/share/nemoclaw/corporate-ca.pem -out /dev/null - node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts verify \ + node scripts/check-messaging-plan-image-boundary.mts verify \ nemoclaw-hermes-plan-boundary hermes - name: Clean up Docker auth diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ab076260625..015e18bb5e8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -291,7 +291,7 @@ repos: hooks: - id: stale-dist-check name: Warn if dist/ is older than src/ - entry: node --experimental-strip-types scripts/check-stale-dist.mts + entry: node scripts/check-stale-dist.mts language: system always_run: true pass_filenames: false diff --git a/Dockerfile b/Dockerfile index f6ae9b23396..46bfe54c396 100644 --- a/Dockerfile +++ b/Dockerfile @@ -37,7 +37,7 @@ RUN --network=default /opt/nemoclaw-build-tools/npm-ci-locked.sh \ COPY nemoclaw/src/ /opt/nemoclaw/src/ COPY scripts/checks/verify-openshell-policy-boundary-dependencies.mts /opt/nemoclaw-build-checks/ RUN npm run build \ - && node --experimental-strip-types \ + && node \ /opt/nemoclaw-build-checks/verify-openshell-policy-boundary-dependencies.mts \ /opt/nemoclaw/dist/shared/openshell-policy-boundary.cjs @@ -168,7 +168,7 @@ COPY scripts/checks/materialize-locked-npm-cache-seed.mts /opt/checks/ COPY scripts/lib/reviewed-npm-archive.mts scripts/lib/seed-reviewed-npm-cache.mts /opt/nemoclaw-build-tools/ COPY --from=wechat-npm-archives / /opt/wechat-npm-archives/ RUN --network=none install -d -o root -g root -m 0755 /out/wechat-npm-cache \ - && node --experimental-strip-types /opt/nemoclaw-build-tools/seed-reviewed-npm-cache.mts \ + && node /opt/nemoclaw-build-tools/seed-reviewed-npm-cache.mts \ --lockfile /opt/wechat-runtime/package-lock.json \ --cache /out/wechat-npm-cache \ --registry-origin https://registry.npmjs.org/ \ @@ -180,7 +180,7 @@ RUN --network=none install -d -o root -g root -m 0755 /out/wechat-npm-cache \ --userconfig /dev/null --registry https://registry.npmjs.org/ \ --cache /out/wechat-npm-cache \ && NPM_CONFIG_OFFLINE=true \ - node --experimental-strip-types /opt/nemoclaw-build-tools/reviewed-npm-archive.mts \ + node /opt/nemoclaw-build-tools/reviewed-npm-archive.mts \ --lockfile /opt/wechat-runtime/package-lock.json \ --cache /out/wechat-npm-cache \ --registry-origin https://registry.npmjs.org/ \ @@ -506,7 +506,7 @@ RUN --network=none set -eu; \ *) echo "ERROR: unsupported managed messaging npm target: $TARGETARCH" >&2; exit 1 ;; \ esac; \ install -d -o root -g root -m 0755 /out/npm-cache; \ - node --experimental-strip-types /opt/nemoclaw-build-tools/lib/seed-reviewed-npm-cache.mts \ + node /opt/nemoclaw-build-tools/lib/seed-reviewed-npm-cache.mts \ --lockfile /opt/managed-image-messaging-runtime/package-lock.json \ --cache /out/npm-cache \ --registry-origin https://registry.npmjs.org/ \ @@ -516,7 +516,7 @@ RUN --network=none set -eu; \ --ignore-scripts --omit=dev --legacy-peer-deps \ --userconfig /dev/null --registry https://registry.npmjs.org/ \ --cache /out/npm-cache; \ - node --experimental-strip-types /opt/nemoclaw-build-tools/lib/seed-reviewed-npm-cache.mts \ + node /opt/nemoclaw-build-tools/lib/seed-reviewed-npm-cache.mts \ --packuments-only \ --lockfile /opt/managed-image-messaging-runtime/package-lock.json \ --cache /out/npm-cache \ @@ -686,7 +686,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ + node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private brace-expansion fix for the final filesystem. @@ -695,7 +695,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ + node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private ip-address fix for the final filesystem. When @@ -705,7 +705,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ + node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # Harden: remove unnecessary build tools and network probes from base image (#830) @@ -866,7 +866,7 @@ RUN --network=default \ [ -n "$MCPORTER_LOCK_SHA256" ] \ || { echo "ERROR: Could not hash the committed mcporter lockfile" >&2; exit 1; }; \ MCPORTER_AUDIT_POLICY_SHA256="$(sha256sum /scripts/npm-audit-exceptions.json | awk '{print $1}')"; \ - MCPORTER_EXPECTED_AUDIT_EXCEPTIONS="$(node --experimental-strip-types --input-type=module -e \ + MCPORTER_EXPECTED_AUDIT_EXCEPTIONS="$(node --input-type=module -e \ 'import fs from "node:fs"; import { parseAuditExceptionRegistry } from "/scripts/lib/reviewed-npm-audit.mts"; const policy=parseAuditExceptionRegistry(fs.readFileSync("/scripts/npm-audit-exceptions.json", "utf-8")); const ids=policy.exceptions.filter((entry)=>entry.graph==="mcporter-runtime").map((entry)=>entry.advisory).sort(); process.stdout.write(ids.join(",") || "none");')"; \ MCPORTER_EXPECTED_AUDIT_STATUS=clean; \ if [ "$MCPORTER_EXPECTED_AUDIT_EXCEPTIONS" != "none" ]; then MCPORTER_EXPECTED_AUDIT_STATUS=accepted-exceptions; fi; \ @@ -922,7 +922,7 @@ RUN --network=default \ # files from surviving a same-version reinstall. rm -rf /usr/local/lib/node_modules/openclaw /usr/local/bin/openclaw; \ if [ "$OPENCLAW_VERSION" = "2026.7.1" ]; then \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-lock \ + node /scripts/lib/reviewed-npm-archive.mts --verify-lock \ --lock-sha256 "$OPENCLAW_LOCK_SHA256" \ --lockfile /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json \ --registry-origin https://registry.npmjs.org/ \ @@ -931,7 +931,7 @@ RUN --network=default \ npm --prefix /usr/local/lib/nemoclaw/openclaw-runtime ci \ --ignore-scripts --omit=dev --no-audit --no-fund --no-progress \ --userconfig /dev/null --registry https://registry.npmjs.org/; \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \ + node /scripts/lib/reviewed-npm-archive.mts \ --verify-installed-lock --lock-sha256 "$OPENCLAW_LOCK_SHA256" \ --lockfile /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json \ --install-root /usr/local/lib/nemoclaw/openclaw-runtime \ @@ -941,13 +941,13 @@ RUN --network=default \ ln -s /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/openclaw /usr/local/lib/node_modules/openclaw; \ ln -s /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/.bin/openclaw /usr/local/bin/openclaw; \ else \ - OPENCLAW_SOURCE_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \ + OPENCLAW_SOURCE_PACK_PATH="$(node /scripts/lib/reviewed-npm-archive.mts \ --package-spec "openclaw@${OPENCLAW_VERSION}" --integrity "$EXPECTED_INTEGRITY" \ --tarball-url "$EXPECTED_TARBALL" --label "OpenClaw ${OPENCLAW_VERSION}")"; \ OPENCLAW_PACK_PATH="$OPENCLAW_SOURCE_PACK_PATH"; \ OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_PACK_PATH")"; \ if [ "$OPENCLAW_VERSION" = "2026.3.11" ]; then \ - OPENCLAW_REMEDIATION_JSON="$(node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts \ + OPENCLAW_REMEDIATION_JSON="$(node /scripts/lib/openclaw-npm-remediation.mts \ --archive "$OPENCLAW_SOURCE_PACK_PATH" --package-spec "openclaw@${OPENCLAW_VERSION}" \ --working-directory "$OPENCLAW_PACK_DIR")"; \ OPENCLAW_PACK_PATH="$(node -e 'const value = JSON.parse(process.argv[1]); if (!value.remediated || typeof value.archivePath !== "string") process.exit(1); process.stdout.write(value.archivePath)' "$OPENCLAW_REMEDIATION_JSON")"; \ @@ -967,7 +967,7 @@ RUN --network=default \ if [ "$USE_REVIEWED_BASE_RUNTIME" = "1" ]; then \ echo "INFO: Reusing reviewed base mcporter $CUR_MCPORTER_VER with matching lock provenance"; \ else \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-only \ + node /scripts/lib/reviewed-npm-archive.mts --verify-only \ --package-spec "mcporter@${MCPORTER_VERSION}" --integrity "$MCPORTER_EXPECTED_INTEGRITY" \ --tarball-url "$MCPORTER_EXPECTED_TARBALL" --label "mcporter ${MCPORTER_VERSION}"; \ # Reinstall from the committed lock when matching protected base provenance @@ -989,7 +989,7 @@ RUN --network=default \ [ -f "$MCPORTER_RECEIPT" ] && [ -f "$MCPORTER_RAW_REPORT" ] && printf %s "$NEMOCLAW_MCPORTER_AUDIT_RECEIPT_SHA256" | grep -qxE '[0-9a-f]{64}' \ || { echo "ERROR: cached mcporter audit requires paired receipt, raw report, and receipt SHA-256" >&2; exit 1; }; \ printf '%s %s\n' "$NEMOCLAW_MCPORTER_AUDIT_RECEIPT_SHA256" "$MCPORTER_RECEIPT" | sha256sum -c -; \ -node --experimental-strip-types /scripts/lib/npm-audit-receipt.mts \ +node /scripts/lib/npm-audit-receipt.mts \ --receipt "$MCPORTER_RECEIPT" \ --package-json /usr/local/lib/nemoclaw/mcporter-runtime/package.json \ --package-lock /usr/local/lib/nemoclaw/mcporter-runtime/package-lock.json \ @@ -997,7 +997,7 @@ node --experimental-strip-types /scripts/lib/npm-audit-receipt.mts \ --graph mcporter-runtime --audit-config /scripts/reviewed-npm-audit.json \ --registry https://registry.yarnpkg.com --threshold high --legacy-npmjs true; \ else \ - node --experimental-strip-types /scripts/lib/reviewed-npm-audit.mts \ + node /scripts/lib/reviewed-npm-audit.mts \ --directory /usr/local/lib/nemoclaw/mcporter-runtime \ --exceptions /scripts/npm-audit-exceptions.json --graph mcporter-runtime --threshold high; \ fi @@ -1362,7 +1362,7 @@ RUN set -eu; \ # Removal criteria: drop when upstream OpenClaw fixes openclaw/openclaw#70164 # and openclaw/openclaw#50298, or when NemoClaw no longer ships an affected OpenClaw. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-chat-send.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-chat-send.mts \ /usr/local/lib/node_modules/openclaw/dist # Keep OpenClaw 2026.7.1 scope-upgrade approvals inside the gateway's @@ -1377,7 +1377,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-chat- # Removal criteria: drop when upstream OpenClaw can approve the same bounded # self-upgrade through the gateway using only operator.pairing. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts \ /usr/local/lib/node_modules/openclaw/dist # Keep backend RPC initiated by the OpenClaw gateway daemon on loopback while @@ -1392,7 +1392,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-devic # gateway URL. # hadolint ignore=DL3059 RUN if [ "$OPENCLAW_VERSION" = "2026.7.1" ]; then \ - node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts \ + node /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts \ /usr/local/lib/node_modules/openclaw/dist; \ fi @@ -1408,7 +1408,7 @@ RUN if [ "$OPENCLAW_VERSION" = "2026.7.1" ]; then \ # Removal criteria: drop when upstream OpenClaw emits these structured fields # from its assistant error formatter for unreachable inference failures. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts \ /usr/local/lib/node_modules/openclaw/dist # Patch OpenClaw's MCP stdio launcher so npx-backed MCP servers run with -y. @@ -1418,7 +1418,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-issue # Removal criteria: drop when upstream OpenClaw normalizes npx MCP server args # and emits actionable MCP startup timeout diagnostics. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-npx.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-mcp-npx.mts \ /usr/local/lib/node_modules/openclaw/dist # Recover from a transient remote Streamable HTTP MCP startup failure. OpenClaw @@ -1432,7 +1432,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-n # Removal criterion: drop when upstream OpenClaw provides bounded startup retry, # negative-catalog invalidation, and temporary-transport failure attribution. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts \ /usr/local/lib/node_modules/openclaw/dist # Keep OpenClaw's 1,500 ms tools/list catalog timeout by default. A validated @@ -1443,7 +1443,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-r # Removal criterion: drop when upstream OpenClaw exposes an equivalent bounded # tools/list-only runtime setting. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts \ /usr/local/lib/node_modules/openclaw/dist # Emit a redacted managed-transport diagnostic when a remote Streamable HTTP MCP @@ -1459,14 +1459,14 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-t # Removal criterion: drop when upstream OpenClaw emits phase-classified, # redacted transport diagnostics for remote MCP fetch failures. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-managed-transport-diagnostics.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-managed-transport-diagnostics.mts \ /usr/local/lib/node_modules/openclaw/dist # Run the compact tool catalog shim for OpenClaw selection runtimes that still # need it. OpenClaw 2026.7.1 ships a built-in catalog surface, so the script # skips cleanly after classifying the compiled selection-*.js shape. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts \ /usr/local/lib/node_modules/openclaw/dist # OpenClaw 2026.7.1 moved gateway startup work into shared and per-agent SQLite @@ -1484,7 +1484,7 @@ RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-tool- # group-shared state databases and split-user cache migrations without # startup warnings. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts \ +RUN node /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts \ /usr/local/lib/node_modules/openclaw/dist # Set up blueprint for local resolution. @@ -1683,7 +1683,7 @@ USER sandbox # block until after build-time OpenClaw doctor/plugin commands complete. RUN NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0 \ NEMOCLAW_OPENCLAW_MANAGED_PROXY=0 \ - node --experimental-strip-types /scripts/generate-openclaw-config.mts + node /scripts/generate-openclaw-config.mts # Validate the patched OpenClaw tool-search contract against real generated # configs for both supported disclosure modes. This runs at image build time so @@ -1701,8 +1701,8 @@ RUN set -eu; \ NEMOCLAW_TOOL_DISCLOSURE="$mode" \ NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0 \ NEMOCLAW_OPENCLAW_MANAGED_PROXY=0 \ - node --experimental-strip-types /scripts/generate-openclaw-config.mts; \ - node --experimental-strip-types /scripts/validate-openclaw-tool-search.mts \ + node /scripts/generate-openclaw-config.mts; \ + node /scripts/validate-openclaw-tool-search.mts \ /usr/local/lib/node_modules/openclaw/dist \ "$validation_home/.openclaw/openclaw.json" \ "$mode" \ @@ -1740,7 +1740,7 @@ RUN --network=none --mount=from=openclaw-optional-plugin-archives,target=/opt/ne "$plugin_archive" "$expected_integrity"; \ printf '%s\n' "$plugin_archive"; \ else \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \ + node /scripts/lib/reviewed-npm-archive.mts \ --package-spec "$plugin_spec" --integrity "$expected_integrity" \ --tarball-url "$expected_tarball" --label "OpenClaw plugin ${plugin_spec}"; \ fi; \ @@ -1753,7 +1753,7 @@ RUN --network=none --mount=from=openclaw-optional-plugin-archives,target=/opt/ne plugin_install_archive="$plugin_archive"; \ case "$plugin_spec" in \ "@openclaw/diagnostics-otel@2026.7.1") \ - remediation_json="$(node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts \ + remediation_json="$(node /scripts/lib/openclaw-npm-remediation.mts \ --archive "$plugin_archive" --package-spec "$plugin_spec" \ --working-directory "$plugin_work_root")"; \ plugin_install_archive="$(node -e 'const value = JSON.parse(process.argv[1]); if (!value.remediated || typeof value.archivePath !== "string") process.exit(1); process.stdout.write(value.archivePath)' "$remediation_json")" \ @@ -1808,7 +1808,7 @@ RUN chmod 755 /src/lib/messaging/applier/build/messaging-build-applier.mts \ # forwards explicit runtime env, so nemoclaw-start reads this generic artifact # when the env plan is absent. # hadolint ignore=DL3059 -RUN OPENCLAW_VERSION="${OPENCLAW_VERSION}" node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase runtime-setup +RUN OPENCLAW_VERSION="${OPENCLAW_VERSION}" node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase runtime-setup USER sandbox # npm still needs a writable _cacache/tmp while OpenClaw packs the verified archive, @@ -1843,7 +1843,7 @@ RUN --mount=from=openclaw-managed-messaging-npm-cache,source=/out/npm-cache,targ fi; \ NEMOCLAW_WECHAT_NPM_INSTALL_CACHE="$install_cache" \ OPENCLAW_VERSION="${OPENCLAW_VERSION}" \ - node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts \ + node /src/lib/messaging/applier/build/messaging-build-applier.mts \ --agent openclaw --phase "$messaging_phase"; \ rm -rf "$install_cache"; \ trap - EXIT; \ @@ -1984,7 +1984,7 @@ RUN NPM_CONFIG_IGNORE_SCRIPTS=true npm_config_ignore_scripts=true \ # Apply messaging render and post-agent-install build-file hooks after agent/plugin installation. # hadolint ignore=DL3059,DL4006 -RUN OPENCLAW_VERSION="${OPENCLAW_VERSION}" node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase post-agent-install +RUN OPENCLAW_VERSION="${OPENCLAW_VERSION}" node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase post-agent-install # A managed image is a neutral capability carrier, not an all-channels-enabled # deployment. Regenerate after every optional plugin is installed so OpenClaw's @@ -1992,7 +1992,7 @@ RUN OPENCLAW_VERSION="${OPENCLAW_VERSION}" node --experimental-strip-types /src/ # Validate the generated file through the pinned OpenClaw CLI. # hadolint ignore=DL3059,DL4006,SC2016 RUN if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then \ - node --experimental-strip-types /scripts/generate-openclaw-config.mts; \ + node /scripts/generate-openclaw-config.mts; \ validation="$(openclaw config validate --json)"; \ node -e 'const result=JSON.parse(process.argv[1]); if (result.valid !== true) process.exit(1)' "$validation"; \ node -e 'const fs=require("node:fs"), path=require("node:path"); const config=JSON.parse(fs.readFileSync("/sandbox/.openclaw/openclaw.json", "utf8")); const root="/usr/local/lib/node_modules/openclaw/dist/extensions"; const bundled=fs.readdirSync(root, {withFileTypes:true}).filter((entry)=>entry.isDirectory()).map((entry)=>entry.name).flatMap((id)=>{ const packagePath=path.join(root, id, "package.json"); if (!fs.existsSync(packagePath)) return []; const packageManifest=JSON.parse(fs.readFileSync(packagePath, "utf8")); if (!packageManifest.openclaw?.channel?.id) return []; const pluginManifest=JSON.parse(fs.readFileSync(path.join(root, id, "openclaw.plugin.json"), "utf8")); return [{channelId:packageManifest.openclaw.channel.id, pluginId:pluginManifest.id}]; }); if (!bundled.some(({channelId})=>channelId === "imessage") || !bundled.some(({channelId})=>channelId === "telegram")) throw new Error(`unexpected bundled OpenClaw channel inventory: ${bundled.map(({channelId})=>channelId).join(",")}`); for (const {channelId, pluginId} of bundled) { if (config.plugins?.entries?.[pluginId]?.enabled !== false || config.channels?.[channelId]?.enabled !== false) throw new Error(`bundled OpenClaw channel is not neutral: ${channelId}`); }'; \ diff --git a/Dockerfile.base b/Dockerfile.base index 26308e02a30..60fe775ddf4 100644 --- a/Dockerfile.base +++ b/Dockerfile.base @@ -435,31 +435,31 @@ COPY scripts/upgrade-bundled-npm.mts /scripts/upgrade-bundled-npm.mts # npm 10.9.8 in the pinned Node 22 image bundles an affected node-tar copy. # Replace it before npm processes the reviewed npm archive. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Upgrade the complete private npm tree so its sigstore, brace-expansion, and # picomatch packages meet the reviewed security floors. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/upgrade-bundled-npm.mts \ +RUN node /scripts/upgrade-bundled-npm.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 restores affected tar 7.5.19. Replace it from the # registry- and SRI-verified 7.5.21 archive before any npm consumers run. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 contains brace-expansion 5.0.7. Replace only that private # package from the reviewed 5.0.9 archive after the complete npm upgrade. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 contains ip-address 10.2.0. Replace only that private package # with the reviewed 10.3.1 archive after the complete npm upgrade. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ +RUN node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # Keep OpenClaw's jiti-generated source cache out of /tmp so provider marker @@ -510,7 +510,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep ACTUAL_OPENCLAW_LOCK_SHA256="$(sha256sum /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json | awk '{print $1}')"; \ [ "$ACTUAL_OPENCLAW_LOCK_SHA256" = "$OPENCLAW_LOCK_SHA256" ] \ || { echo "Error: OpenClaw lock SHA-256 mismatch (expected $OPENCLAW_LOCK_SHA256, found $ACTUAL_OPENCLAW_LOCK_SHA256)"; exit 1; }; \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-lock \ + node /scripts/lib/reviewed-npm-archive.mts --verify-lock \ --lock-sha256 "$OPENCLAW_LOCK_SHA256" \ --lockfile /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json \ --registry-origin https://registry.npmjs.org/ \ @@ -520,7 +520,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep npm --prefix /usr/local/lib/nemoclaw/openclaw-runtime ci \ --ignore-scripts --omit=dev --no-audit --no-fund --no-progress \ --userconfig /dev/null --registry https://registry.npmjs.org/; \ - node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \ + node /scripts/lib/reviewed-npm-archive.mts \ --verify-installed-lock --lock-sha256 "$OPENCLAW_LOCK_SHA256" \ --lockfile /usr/local/lib/nemoclaw/openclaw-runtime/package-lock.json \ --install-root /usr/local/lib/nemoclaw/openclaw-runtime \ @@ -531,7 +531,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep ln -s /usr/local/lib/nemoclaw/openclaw-runtime/node_modules/.bin/openclaw /usr/local/bin/openclaw; \ OPENCLAW_RECIPE='locked-ci+reviewed-lifecycle-v2'; \ else \ - OPENCLAW_SOURCE_PACK_PATH="$(node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts \ + OPENCLAW_SOURCE_PACK_PATH="$(node /scripts/lib/reviewed-npm-archive.mts \ --package-spec "openclaw@${OPENCLAW_VERSION}" --integrity "$EXPECTED_INTEGRITY" \ --tarball-url "$EXPECTED_TARBALL" --label "OpenClaw ${OPENCLAW_VERSION}")"; \ if [ -z "$OPENCLAW_SOURCE_PACK_PATH" ] || [ ! -f "$OPENCLAW_SOURCE_PACK_PATH" ] || [ -L "$OPENCLAW_SOURCE_PACK_PATH" ]; then \ @@ -540,7 +540,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep OPENCLAW_PACK_PATH="$OPENCLAW_SOURCE_PACK_PATH"; \ OPENCLAW_PACK_DIR="$(dirname "$OPENCLAW_PACK_PATH")"; \ if [ "$OPENCLAW_VERSION" = "2026.3.11" ]; then \ - OPENCLAW_REMEDIATION_JSON="$(node --experimental-strip-types /scripts/lib/openclaw-npm-remediation.mts \ + OPENCLAW_REMEDIATION_JSON="$(node /scripts/lib/openclaw-npm-remediation.mts \ --archive "$OPENCLAW_SOURCE_PACK_PATH" --package-spec "openclaw@${OPENCLAW_VERSION}" \ --working-directory "$OPENCLAW_PACK_DIR")"; \ OPENCLAW_PACK_PATH="$(node -e 'const value = JSON.parse(process.argv[1]); if (!value.remediated || typeof value.archivePath !== "string") process.exit(1); process.stdout.write(value.archivePath)' "$OPENCLAW_REMEDIATION_JSON")"; \ @@ -567,7 +567,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep && if [ -z "$MCPORTER_EXPECTED_INTEGRITY" ]; then \ echo "ERROR: mcporter ${MCPORTER_VERSION} has no committed npm integrity pin" >&2; exit 1; \ fi \ - && node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-only \ + && node /scripts/lib/reviewed-npm-archive.mts --verify-only \ --package-spec "mcporter@${MCPORTER_VERSION}" --integrity "$MCPORTER_EXPECTED_INTEGRITY" \ --tarball-url "$MCPORTER_EXPECTED_TARBALL" --label "mcporter ${MCPORTER_VERSION}" \ && rm -rf /usr/local/lib/node_modules/mcporter /usr/local/bin/mcporter \ @@ -585,7 +585,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep [ -f "$MCPORTER_RECEIPT" ] && [ -f "$MCPORTER_RAW_REPORT" ] && printf %s "$NEMOCLAW_MCPORTER_AUDIT_RECEIPT_SHA256" | grep -qxE '[0-9a-f]{64}' \ || { echo "ERROR: cached mcporter audit requires paired receipt, raw report, and receipt SHA-256" >&2; exit 1; }; \ printf '%s %s\n' "$NEMOCLAW_MCPORTER_AUDIT_RECEIPT_SHA256" "$MCPORTER_RECEIPT" | sha256sum -c -; \ - node --experimental-strip-types /scripts/lib/npm-audit-receipt.mts \ + node /scripts/lib/npm-audit-receipt.mts \ --receipt "$MCPORTER_RECEIPT" \ --package-json /usr/local/lib/nemoclaw/mcporter-runtime/package.json \ --package-lock /usr/local/lib/nemoclaw/mcporter-runtime/package-lock.json \ @@ -596,7 +596,7 @@ RUN --mount=type=bind,source=nemoclaw-blueprint/blueprint.yaml,target=/tmp/bluep --result /tmp/mcporter-npm-audit-policy.json \ && cp "$MCPORTER_RAW_REPORT" /tmp/mcporter-npm-audit.json; \ else \ - node --experimental-strip-types /scripts/lib/reviewed-npm-audit.mts \ + node /scripts/lib/reviewed-npm-audit.mts \ --directory /usr/local/lib/nemoclaw/mcporter-runtime \ --exceptions /scripts/npm-audit-exceptions.json --graph mcporter-runtime --threshold high \ --report /tmp/mcporter-npm-audit.json --result /tmp/mcporter-npm-audit-policy.json; \ diff --git a/agents/hermes/Dockerfile b/agents/hermes/Dockerfile index fb891e24cd1..5572513a3d2 100644 --- a/agents/hermes/Dockerfile +++ b/agents/hermes/Dockerfile @@ -335,7 +335,7 @@ RUN grep -Fq 'from tools.lazy_deps import install_specs' /opt/hermes/hermes_cli/ # base freshness. Reassert the idempotent npm-private node-tar fix from the # locked cache seed so protected rebuilds remain network-disabled. COPY tools/mcp-tool-discovery-runtime/npm-cache-seed/tar-7.5.21.tgz /tmp/nemoclaw-bundled-npm-tar.tgz -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm \ --archive /tmp/nemoclaw-bundled-npm-tar.tgz @@ -347,7 +347,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ + node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private ip-address fix for the final filesystem. When @@ -357,7 +357,7 @@ RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export NODE_EXTRA_CA_CERTS=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ + node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # Keep the final image contract explicit even when the published base image @@ -777,7 +777,7 @@ RUN printf '%s %s\n' \ "$NEMOCLAW_HERMES_LANGFUSE_PATCHER_SHA256" /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts \ | sha256sum -c - \ || { echo "ERROR: patch-hermes-langfuse-credentials.mts hash mismatch (update NEMOCLAW_HERMES_LANGFUSE_PATCHER_SHA256)" >&2; exit 1; } -RUN node --experimental-strip-types \ +RUN node \ /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts \ /opt/hermes/plugins/observability/langfuse/__init__.py \ && /opt/hermes/.venv/bin/python -I \ @@ -921,7 +921,7 @@ RUN case "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" in \ # Bake reduced messaging runtime metadata for the entrypoint. Hermes runtime # config refresh consumes generic manifest-owned aliases from this artifact. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase runtime-setup \ +RUN node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase runtime-setup \ && runtime_plan=/usr/local/share/nemoclaw/messaging-runtime-plan.json \ && { [ ! -f "$runtime_plan" ] || { test ! -L "$runtime_plan" \ && node -e "const fs=require('fs'); const path=process.argv[1]; const st=fs.statSync(path); if (!st.isFile() || st.uid !== 0 || st.gid !== 0 || (st.mode & 0o022) !== 0) throw new Error('unsafe runtime plan file metadata'); const p=JSON.parse(fs.readFileSync(path,'utf8')); for (const k of ['agentRender','buildSteps','stateUpdates','healthChecks']) if (Object.hasOwn(p,k)) throw new Error('runtime plan contains unreduced key '+k); const runtimeSetup=p.runtimeSetup; const isObject=(v)=>v && typeof v === 'object' && !Array.isArray(v); if (!isObject(runtimeSetup) || !Array.isArray(runtimeSetup.nodePreloads) || !Array.isArray(runtimeSetup.envAliases) || !Array.isArray(runtimeSetup.secretScans) || !runtimeSetup.nodePreloads.every(isObject) || !runtimeSetup.envAliases.every(isObject) || !runtimeSetup.secretScans.every(isObject)) throw new Error('runtime plan missing reduced runtimeSetup shape');" "$runtime_plan"; }; } @@ -937,7 +937,7 @@ RUN unset SSL_CERT_FILE REQUESTS_CA_BUNDLE; \ export SSL_CERT_FILE=/usr/local/share/nemoclaw/corporate-ca.pem; \ export REQUESTS_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase agent-install + node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase agent-install # Managed images have no serialized messaging plan. Install their complete # reviewed package union from the selected wheel stage. Portable Podman uses the @@ -948,7 +948,7 @@ COPY --from=hermes-managed-teams-wheels / /opt/nemoclaw-hermes-teams-wheels/ # hadolint ignore=DL3059 RUN if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then \ UV_OFFLINE=true UV_FIND_LINKS=/opt/nemoclaw-hermes-teams-wheels \ - node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts \ + node /src/lib/messaging/applier/build/messaging-build-applier.mts \ --agent hermes --phase managed-image-capability-union; \ fi \ && /opt/hermes/.venv/bin/python -I -c \ @@ -1104,7 +1104,7 @@ USER sandbox # Apply messaging render and post-agent-install build-file hooks after agent/plugin installation. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase post-agent-install +RUN node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase post-agent-install # Write the default SOUL.md (agent identity) for the sandboxed agent. # This is the stock Hermes default soul (hermes_cli/default_soul.py, diff --git a/agents/hermes/Dockerfile.base b/agents/hermes/Dockerfile.base index 0c997f2715c..366d8cf59c4 100644 --- a/agents/hermes/Dockerfile.base +++ b/agents/hermes/Dockerfile.base @@ -274,31 +274,31 @@ COPY scripts/upgrade-bundled-npm.mts /scripts/upgrade-bundled-npm.mts # npm 11.16.0 in Node.js 24.18.1 bundles an affected node-tar copy. # Patch that private package after curl is installed and before npm processes # the reviewed npm archive. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Upgrade the complete private npm tree before npm processes the # checksum-pinned Hermes release lockfiles. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/upgrade-bundled-npm.mts \ +RUN node /scripts/upgrade-bundled-npm.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 restores affected tar 7.5.19. Replace it from the # registry- and SRI-verified 7.5.21 archive before any npm consumers run. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private brace-expansion 5.0.7 package with the # registry- and SRI-pinned 5.0.9 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private ip-address 10.2.0 package with the # registry- and SRI-pinned 10.3.1 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ +RUN node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # setpriv runtime contract for gateway and sandbox privilege separation. diff --git a/agents/hermes/image-build-probes.py b/agents/hermes/image-build-probes.py index 15edab34931..c76ea66372f 100644 --- a/agents/hermes/image-build-probes.py +++ b/agents/hermes/image-build-probes.py @@ -39,7 +39,7 @@ def prepare_generated_config( ) _run_required_build_command( "Hermes config generator", - [str(node), "--experimental-strip-types", str(generator)], + [str(node), str(generator)], env=child_env, ) diff --git a/agents/langchain-deepagents-code/Dockerfile b/agents/langchain-deepagents-code/Dockerfile index f0df1123f02..3f80d9aca3d 100644 --- a/agents/langchain-deepagents-code/Dockerfile +++ b/agents/langchain-deepagents-code/Dockerfile @@ -154,12 +154,12 @@ COPY scripts/patch-bundled-npm-tar.mts /scripts/patch-bundled-npm-tar.mts # The final managed image owns the shipped dependency boundary independently # of base freshness. Reassert the idempotent npm-private node-tar fix here. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private brace-expansion fix for the final filesystem. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private ip-address fix for the final filesystem. When @@ -168,7 +168,7 @@ RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.m RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ + node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm RUN set -eu; \ @@ -356,7 +356,7 @@ USER sandbox RUN mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0 \ && cp -r /opt/nemoclaw-blueprint/* /sandbox/.nemoclaw/blueprints/0.1.0/ \ - && node --experimental-strip-types /opt/nemoclaw-deepagents-code/generate-config.ts \ + && node /opt/nemoclaw-deepagents-code/generate-config.ts \ && chmod 660 /sandbox/.deepagents/config.toml USER root diff --git a/agents/langchain-deepagents-code/Dockerfile.base b/agents/langchain-deepagents-code/Dockerfile.base index b205c6bfd4a..17a2391c8fe 100644 --- a/agents/langchain-deepagents-code/Dockerfile.base +++ b/agents/langchain-deepagents-code/Dockerfile.base @@ -240,31 +240,31 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Node remains available to the managed terminal at runtime, so remediate # npm's private node-tar copy after curl is installed even though Deep Agents # Code itself is Python. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace the complete private npm tree so managed-terminal npm commands use # the reviewed dependency set. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/upgrade-bundled-npm.mts \ +RUN node /scripts/upgrade-bundled-npm.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 restores affected tar 7.5.19. Replace it from the # registry- and SRI-verified 7.5.21 archive before any npm consumers run. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private brace-expansion 5.0.7 package with the # registry- and SRI-pinned 5.0.9 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private ip-address 10.2.0 package with the # registry- and SRI-pinned 10.3.1 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ +RUN node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # setpriv runtime contract for sandbox privilege separation. diff --git a/agents/openclaw/dependency-review.md b/agents/openclaw/dependency-review.md index 39299a736d8..2477d64aecb 100644 --- a/agents/openclaw/dependency-review.md +++ b/agents/openclaw/dependency-review.md @@ -15,7 +15,7 @@ Update it and `agents/openclaw/mcporter-runtime/package*.json` together whenever - Registry metadata independently queried from npm: 2026-06-30. - Locked graph: `agents/openclaw/mcporter-runtime/package-lock.json` (npm lockfile version 3). - Lock regeneration command: `npm --prefix agents/openclaw/mcporter-runtime install --package-lock-only --ignore-scripts --omit=dev` -- Advisory command: `npm --prefix agents/openclaw/mcporter-runtime ci --ignore-scripts --omit=dev && node --experimental-strip-types scripts/lib/reviewed-npm-audit.mts --directory agents/openclaw/mcporter-runtime --exceptions ci/npm-audit-exceptions.json --graph mcporter-runtime --threshold high && npm --prefix agents/openclaw/mcporter-runtime audit signatures --registry=https://registry.yarnpkg.com --omit=dev` +- Advisory command: `npm --prefix agents/openclaw/mcporter-runtime ci --ignore-scripts --omit=dev && node scripts/lib/reviewed-npm-audit.mts --directory agents/openclaw/mcporter-runtime --exceptions ci/npm-audit-exceptions.json --graph mcporter-runtime --threshold high && npm --prefix agents/openclaw/mcporter-runtime audit signatures --registry=https://registry.yarnpkg.com --omit=dev` - Advisory review date: 2026-08-11. - Advisory result: `0` known vulnerabilities across the resolved production dependency graph. npm verified registry signatures for all `120` resolved packages and attestations for `14` packages. - Security override: `@hono/node-server@2.0.11` (`sha512-bjD221KPLoJTWUwso1J6fGKiTXEUFedG/s0visavY4zakFPkeGURMRNly+FhBHs7T8Dz4qHaZIMX9ZoJHSJtKA==`) replaces the SDK's vulnerable `1.19.14` resolution for `GHSA-frvp-7c67-39w9` and the previously reviewed `2.0.5` resolution affected by `GHSA-9mqv-5hh9-4cgg`. `2.0.5` is the first patched release for `GHSA-frvp-7c67-39w9`. The reviewed v2 range retains the `getRequestListener` API used by `@modelcontextprotocol/sdk`; its Node.js 20 floor is below NemoClaw's Node.js 22.19 floor, and the `/vercel` adapter is not consumed. Mcporter's production path imports the SDK's client transport, not the server adapter, and the image build still exercises the installed CLI after the locked install. Remove the override when the SDK's declared range resolves to a reviewed release outside both affected ranges. diff --git a/agents/pi/Dockerfile b/agents/pi/Dockerfile index 9719437f401..e3deadbf6c3 100644 --- a/agents/pi/Dockerfile +++ b/agents/pi/Dockerfile @@ -123,12 +123,12 @@ COPY scripts/patch-bundled-npm-tar.mts /scripts/patch-bundled-npm-tar.mts # The final managed image owns the shipped dependency boundary independently # of base freshness. Reassert the idempotent npm-private node-tar fix here. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private brace-expansion fix for the final filesystem. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Reassert the npm-private ip-address fix for the final filesystem. When @@ -137,7 +137,7 @@ RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.m RUN if [ -f /usr/local/share/nemoclaw/corporate-ca.pem ]; then \ export CURL_CA_BUNDLE=/usr/local/share/nemoclaw/corporate-ca.pem; \ fi; \ - node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ + node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm ARG PI_VERSION=0.84.1 @@ -229,7 +229,7 @@ USER sandbox RUN umask 077 \ && mkdir -p /sandbox/.nemoclaw/blueprints/0.1.0 \ && cp -r /opt/nemoclaw-blueprint/* /sandbox/.nemoclaw/blueprints/0.1.0/ \ - && node --experimental-strip-types /opt/nemoclaw-pi/generate-config.ts \ + && node /opt/nemoclaw-pi/generate-config.ts \ && test "$(stat -c %a /sandbox/.pi/agent/models.json)" = "600" # hadolint ignore=DL3066 diff --git a/agents/pi/Dockerfile.base b/agents/pi/Dockerfile.base index 8385bceb7d9..d8ad81ac041 100644 --- a/agents/pi/Dockerfile.base +++ b/agents/pi/Dockerfile.base @@ -243,31 +243,31 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ # Pi runs on Node.js, so remediate npm's private node-tar copy after curl is # installed. -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace the complete private npm tree so managed-terminal npm commands use # the reviewed dependency set. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/upgrade-bundled-npm.mts \ +RUN node /scripts/upgrade-bundled-npm.mts \ --npm-root /usr/local/lib/node_modules/npm # npm 11.18.0 restores affected tar 7.5.19. Replace it from the # registry- and SRI-verified 7.5.21 archive before any npm consumers run. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts \ +RUN node /scripts/patch-bundled-npm-tar.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private brace-expansion 5.0.7 package with the # registry- and SRI-pinned 5.0.9 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts \ +RUN node /scripts/patch-bundled-npm-brace-expansion.mts \ --npm-root /usr/local/lib/node_modules/npm # Replace npm 11.18.0's private ip-address 10.2.0 package with the # registry- and SRI-pinned 10.3.1 release. # hadolint ignore=DL3059 -RUN node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts \ +RUN node /scripts/lib/patch-bundled-npm-ip-address.mts \ --npm-root /usr/local/lib/node_modules/npm # setpriv runtime contract for sandbox privilege separation. diff --git a/docs/resources/starter-prompt.md b/docs/resources/starter-prompt.md index 4fa477448b8..2738f979d21 100644 --- a/docs/resources/starter-prompt.md +++ b/docs/resources/starter-prompt.md @@ -155,8 +155,8 @@ Before collecting secrets, determine every environment-variable name and the com Do not generate, rewrite, or redesign the helper or form. Use this reviewed pair without modification: -- Helper: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/dd61a307d7ddf7be99de8ff1e2678fb8ef42f8e6/scripts/local-credential-helper.mts` (SHA-256 `1a42bbe8dbc9003cb79d4e641b53760571aacd85293671aee97c09c0746fef33`). -- Form: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/dd61a307d7ddf7be99de8ff1e2678fb8ef42f8e6/docs/resources/local-credential-form.html` (SHA-256 `5512a256e0ad7c63a26ab82cf4f5924e98652097172ab8a5dc9d9358dd4f6ae8`). +- Helper: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/11e0bb209103b03ee8239cbc307d1cb5d3521866/scripts/local-credential-helper.mts` (SHA-256 `72c187067dca6423e7aa7fa4bfab660e4202805f503c79520d8a0cf24869b668`). +- Form: `https://raw.githubusercontent.com/NVIDIA/NemoClaw/11e0bb209103b03ee8239cbc307d1cb5d3521866/docs/resources/local-credential-form.html` (SHA-256 `5512a256e0ad7c63a26ab82cf4f5924e98652097172ab8a5dc9d9358dd4f6ae8`). - Treat the two immutable URL and digest pairs as one reviewed trust boundary; before executing the helper, compute the SHA-256 digest of both downloaded files and compare each result with its pinned digest. - If either digest differs, do not execute the helper; delete both temporary files and stop. @@ -171,7 +171,7 @@ Use this reviewed pair without modification: - Never omit the literal `--`. - Never use a relative, alias-only, or PATH-only approved executable. - Never put credentials in argv. -- Command shape: `node --experimental-strip-types --execution-profile --form
--field NAME:secret -- `. +- Command shape: `node --execution-profile --form --field NAME:secret -- `. - Use **Preview Credentials**, **Edit**, then **Confirm and Run Approved Command**. - If the outcome is unknown, check whether the command ran; do not retry or resubmit blindly. - Keep secrets in memory only long enough to start the command. diff --git a/docs/security/advisory-early-warning.md b/docs/security/advisory-early-warning.md index 5f364ad4255..7702260c782 100644 --- a/docs/security/advisory-early-warning.md +++ b/docs/security/advisory-early-warning.md @@ -54,11 +54,11 @@ With `--output`, it writes the requested local signals file: ```sh # List inventory package names (one per line), the input for advisory queries. -node --experimental-strip-types scripts/advisory-early-warning-scan.mts \ +node scripts/advisory-early-warning-scan.mts \ --list-packages # Correlate fetched advisory records with the inventory. -node --experimental-strip-types scripts/advisory-early-warning-scan.mts \ +node scripts/advisory-early-warning-scan.mts \ --advisories advisories.json --output signals.json ``` diff --git a/package.json b/package.json index b5256b253b4..6296e476b8d 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,7 @@ "dev:setup": "bash scripts/dev-setup.sh", "dev:doctor": "bash scripts/dev-setup.sh --doctor", "agent": "pi", - "review:local": "node --experimental-strip-types --no-warnings tools/pr-review-advisor/local-review.mts", + "review:local": "node --no-warnings tools/pr-review-advisor/local-review.mts", "test": "npm run clean:cli && npm --prefix nemoclaw run clean && npm run build:cli && npm --prefix nemoclaw run build && vitest run --project cli --project integration --project installer-integration --project package-contract --project plugin --project e2e-support", "test:spec": "npm test -- --reporter=tree", "test:fast": "npm run clean:cli && npm run catalog:compile && vitest run --project cli --project plugin --project e2e-support", @@ -42,7 +42,7 @@ "test:watch": "npm run catalog:compile && vitest watch --project cli --project plugin --project e2e-support", "test:shuffle": "npm run catalog:compile && vitest run --project cli --project plugin --project e2e-support --sequence.shuffle.tests --coverage=false", "test:diagnose:leaks": "npm run catalog:compile && vitest run --project cli --project plugin --project e2e-support --detectAsyncLeaks --coverage=false --reporter=default --reporter=hanging-process", - "test:e2e-phases:check": "npm run catalog:compile && npm run build:policy-boundary && node --experimental-strip-types --no-warnings tools/e2e/check-semantic-phases.mts", + "test:e2e-phases:check": "npm run catalog:compile && npm run build:policy-boundary && node --no-warnings tools/e2e/check-semantic-phases.mts", "test:runtime-audit": "tsx scripts/audit-test-runtime.mts", "test:integration": "npm run clean:cli && npm run build:cli && vitest run --project integration --project installer-integration", "test:package": "npm run clean:cli && npm --prefix nemoclaw run clean && npm run build:cli && npm --prefix nemoclaw run build && vitest run --project package-contract", @@ -77,7 +77,7 @@ "config-schema:generate": "npm run build:policy-boundary && tsx scripts/config/generate-nemoclaw-config-schema.mts", "config-schema:check": "npm run build:policy-boundary && tsx scripts/config/generate-nemoclaw-config-schema.mts --check", "catalog:verify-hugging-face": "npm run catalog:compile && tsx tools/managed-inference/verify-hugging-face-models.ts", - "build:cli": "npm run prune:retired-cli && npm run build:policy-boundary && npm run build:runner-boundary && tsc -p tsconfig.src.json && node --experimental-strip-types --no-warnings scripts/lib/package-blueprint-runner-runtime.mts && node dist/lib/core/generate-build-identity.js && node dist/lib/inference/serving/generate-catalog.js && node dist/lib/cli/generate-oclif-metadata-manifest.js && if find nemoclaw-blueprint/scripts -name '*.ts' -print -quit | grep -q .; then tsc -p nemoclaw-blueprint/tsconfig.json; fi", + "build:cli": "npm run prune:retired-cli && npm run build:policy-boundary && npm run build:runner-boundary && tsc -p tsconfig.src.json && node --no-warnings scripts/lib/package-blueprint-runner-runtime.mts && node dist/lib/core/generate-build-identity.js && node dist/lib/inference/serving/generate-catalog.js && node dist/lib/cli/generate-oclif-metadata-manifest.js && if find nemoclaw-blueprint/scripts -name '*.ts' -print -quit | grep -q .; then tsc -p nemoclaw-blueprint/tsconfig.json; fi", "build:runner-boundary": "node -e \"require('node:fs').rmSync('nemoclaw/runner-dist', { recursive: true, force: true })\" && tsc -p nemoclaw/tsconfig.runner.json", "clean:cli": "node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"", "prune:retired-cli": "node -e \"const fs = require('node:fs'); const suffixes = ['.js', '.js.map', '.d.ts', '.d.ts.map']; const prefixes = ['dist/commands/deploy', 'dist/lib/actions/deploy', 'dist/lib/actions/sandbox/agent/connect-shields-relock-notice', 'dist/lib/actions/sandbox/agent/passthrough-shields-warning', 'dist/lib/actions/sandbox/backup-shields-window', 'dist/lib/actions/sandbox/rebuild-shields-phase', 'dist/lib/actions/sandbox/rebuild-shields', 'dist/lib/domain/duration', 'dist/lib/policy/merge', 'dist/lib/onboard/runtime-provider/container-state-mutation', 'dist/lib/onboard/runtime-provider/docker-state-mutation', 'dist/lib/onboard/runtime-provider/persisted-engine-lifecycle', 'dist/lib/onboard/runtime-provider/podman-state-mutation', 'dist/lib/onboard/runtime-provider/state-mutation', 'dist/lib/state/mcp-lifecycle-lock/shields-timer-authority']; for (const prefix of prefixes) for (const suffix of suffixes) fs.rmSync(prefix + suffix, { force: true }); for (const directory of ['dist/commands/sandbox/shields', 'dist/lib/deploy', 'dist/lib/shields']) fs.rmSync(directory, { recursive: true, force: true });\"", diff --git a/scripts/advisory-early-warning-scan.mts b/scripts/advisory-early-warning-scan.mts index 27109f7b098..6a9091918f5 100755 --- a/scripts/advisory-early-warning-scan.mts +++ b/scripts/advisory-early-warning-scan.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 // diff --git a/scripts/audit-reviewed-npm-graph.mts b/scripts/audit-reviewed-npm-graph.mts index 80db38ae096..35339e01219 100755 --- a/scripts/audit-reviewed-npm-graph.mts +++ b/scripts/audit-reviewed-npm-graph.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/check-installer-hash.sh b/scripts/check-installer-hash.sh index 2d329c8f963..1662a879ced 100755 --- a/scripts/check-installer-hash.sh +++ b/scripts/check-installer-hash.sh @@ -101,7 +101,7 @@ check_openshell_release_assets() { # removalCondition: replace this parser when both installers directly consume # one canonical machine-readable pin manifest. parser_errors="${workspace}/pin-parser-errors.txt" - if ! pin_records=$(node --experimental-strip-types \ + if ! pin_records=$(node \ "${CHECKER_ROOT}/checks/extract-installer-pins.mts" \ --blueprint "${REPO_ROOT}/nemoclaw-blueprint/blueprint.yaml" \ --installer "$installer" \ diff --git a/scripts/check-messaging-plan-image-boundary.mts b/scripts/check-messaging-plan-image-boundary.mts index 2fd6cc8308f..7c34663cfe6 100644 --- a/scripts/check-messaging-plan-image-boundary.mts +++ b/scripts/check-messaging-plan-image-boundary.mts @@ -700,8 +700,8 @@ function formatError(error: unknown): string { function usage(): string { return [ "Usage:", - " node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts plan ", - " node --experimental-strip-types scripts/check-messaging-plan-image-boundary.mts verify ", + " node scripts/check-messaging-plan-image-boundary.mts plan ", + " node scripts/check-messaging-plan-image-boundary.mts verify ", ].join("\n"); } diff --git a/scripts/checks/build-protected-managed-images.sh b/scripts/checks/build-protected-managed-images.sh index d7cde196dac..53f36695f85 100755 --- a/scripts/checks/build-protected-managed-images.sh +++ b/scripts/checks/build-protected-managed-images.sh @@ -195,7 +195,7 @@ trap 'exit 143' TERM if [[ -n "$cache_from" ]]; then imported_seed="$work_dir/npm-cache-seed-import" - node --experimental-strip-types --no-warnings "$seed_helper" copy \ + node --no-warnings "$seed_helper" copy \ --lockfile "$source_lockfile" \ --seed "$cache_from/npm-cache-seed" \ --output "$imported_seed" \ @@ -208,7 +208,7 @@ if [[ -n "$cache_from" ]]; then cp -pR -- "$imported_seed" "$source_seed_dir" imported_mcp_seed="$work_dir/mcp-runtime-npm-cache-seed-import" - node --experimental-strip-types --no-warnings "$seed_helper" copy \ + node --no-warnings "$seed_helper" copy \ --lockfile "$source_mcp_lockfile" \ --seed "$cache_from/mcp-runtime-npm-cache-seed" \ --output "$imported_mcp_seed" \ @@ -221,7 +221,7 @@ if [[ -n "$cache_from" ]]; then cp -pR -- "$imported_mcp_seed" "$source_mcp_seed_dir" imported_messaging_seed="$work_dir/messaging-npm-cache-seed-import" - node --experimental-strip-types --no-warnings "$seed_helper" copy \ + node --no-warnings "$seed_helper" copy \ --lockfile "$source_messaging_lockfile" \ --seed "$cache_from/messaging-npm-cache-seed" \ --output "$imported_messaging_seed" \ @@ -483,19 +483,19 @@ build_agent \ "$dcode_base" if [[ -n "$cache_to" ]]; then - node --experimental-strip-types --no-warnings "$seed_helper" export \ + node --no-warnings "$seed_helper" export \ --lockfile "$source_lockfile" \ --output "$cache_to/npm-cache-seed" \ --os "$npm_target_os" \ --cpu "$npm_target_cpu" \ --libc "$npm_target_libc" - node --experimental-strip-types --no-warnings "$seed_helper" export \ + node --no-warnings "$seed_helper" export \ --lockfile "$source_mcp_lockfile" \ --output "$cache_to/mcp-runtime-npm-cache-seed" \ --os "$npm_target_os" \ --cpu "$npm_target_cpu" \ --libc "$npm_target_libc" - node --experimental-strip-types --no-warnings "$seed_helper" export \ + node --no-warnings "$seed_helper" export \ --lockfile "$source_messaging_lockfile" \ --output "$cache_to/messaging-npm-cache-seed" \ --os "$npm_target_os" \ diff --git a/scripts/checks/generate-managed-startup-profile-fixture.mts b/scripts/checks/generate-managed-startup-profile-fixture.mts index e27c873bd62..91acd14077a 100755 --- a/scripts/checks/generate-managed-startup-profile-fixture.mts +++ b/scripts/checks/generate-managed-startup-profile-fixture.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/checks/package-openshell-sdk-for-pr.mts b/scripts/checks/package-openshell-sdk-for-pr.mts index 098667020ea..5792ff682dd 100755 --- a/scripts/checks/package-openshell-sdk-for-pr.mts +++ b/scripts/checks/package-openshell-sdk-for-pr.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/checks/prepare-ci-npm-install.mts b/scripts/checks/prepare-ci-npm-install.mts index 2b7b4f0ffb4..1971523e4d5 100755 --- a/scripts/checks/prepare-ci-npm-install.mts +++ b/scripts/checks/prepare-ci-npm-install.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/checks/run-managed-image-direct-e2e.ts b/scripts/checks/run-managed-image-direct-e2e.ts index 21c1317adc8..98c219b7aef 100755 --- a/scripts/checks/run-managed-image-direct-e2e.ts +++ b/scripts/checks/run-managed-image-direct-e2e.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --no-warnings --experimental-strip-types +#!/usr/bin/env -S node --no-warnings // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/dev-tier-selector.mts b/scripts/dev-tier-selector.mts index 4b8961ee4b2..871a9bad927 100644 --- a/scripts/dev-tier-selector.mts +++ b/scripts/dev-tier-selector.mts @@ -8,7 +8,7 @@ // without a real NemoClaw installation. // // Usage: -// node --experimental-strip-types scripts/dev-tier-selector.mts +// node scripts/dev-tier-selector.mts // // This script is intentionally not part of the vitest suite. For automated coverage // of this flow see test/runtime/policy/policy-tiers-onboard.test.ts. diff --git a/scripts/generate-openclaw-config.mts b/scripts/generate-openclaw-config.mts index 1ad3ab5c516..abbe3bba5e5 100755 --- a/scripts/generate-openclaw-config.mts +++ b/scripts/generate-openclaw-config.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 // diff --git a/scripts/install.sh b/scripts/install.sh index 24a70447132..32879c9d4ad 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -5924,7 +5924,7 @@ ensure_station_express_pair() { revision="$(station_installer_revision)" local -a pair_command=( - node --no-warnings --experimental-strip-types "$coordinator" + node --no-warnings "$coordinator" --helper "$helper" --state "$state_file" --revision "$revision" @@ -6025,7 +6025,7 @@ clear_station_dual_pair_resume() { assert_nemoclaw_state_path_safe "$state_file" [[ -e "$state_file" || -L "$state_file" || -e "${state_file}.ssh-binding" || -L "${state_file}.ssh-binding" ]] || return 0 [[ -f "$coordinator" ]] || error "Dual DGX Station preparation coordinator is missing: ${coordinator}" - node --no-warnings --experimental-strip-types "$coordinator" --state "$state_file" --clear-state >/dev/null \ + node --no-warnings "$coordinator" --state "$state_file" --clear-state >/dev/null \ || error "Could not safely clear completed dual DGX Station resume state: ${state_file}" } diff --git a/scripts/lib/npm-audit-receipt.mts b/scripts/lib/npm-audit-receipt.mts index ad1eb8a670a..25c052ec44b 100755 --- a/scripts/lib/npm-audit-receipt.mts +++ b/scripts/lib/npm-audit-receipt.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/lib/openclaw-npm-remediation.mts b/scripts/lib/openclaw-npm-remediation.mts index 0623c3b7851..13b8ba5750a 100755 --- a/scripts/lib/openclaw-npm-remediation.mts +++ b/scripts/lib/openclaw-npm-remediation.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/lib/patch-bundled-npm-ip-address.mts b/scripts/lib/patch-bundled-npm-ip-address.mts index 5d7270b7199..7acc29f1ecb 100755 --- a/scripts/lib/patch-bundled-npm-ip-address.mts +++ b/scripts/lib/patch-bundled-npm-ip-address.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/lib/reviewed-npm-archive.mts b/scripts/lib/reviewed-npm-archive.mts index 2e879f6cc6e..216d7c33743 100755 --- a/scripts/lib/reviewed-npm-archive.mts +++ b/scripts/lib/reviewed-npm-archive.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/lib/reviewed-npm-audit.mts b/scripts/lib/reviewed-npm-audit.mts index b79b271c930..f4ea2724720 100755 --- a/scripts/lib/reviewed-npm-audit.mts +++ b/scripts/lib/reviewed-npm-audit.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/lib/seed-reviewed-npm-cache.mts b/scripts/lib/seed-reviewed-npm-cache.mts index 2afe5eb8e63..b49c47805e4 100755 --- a/scripts/lib/seed-reviewed-npm-cache.mts +++ b/scripts/lib/seed-reviewed-npm-cache.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/local-credential-helper.mts b/scripts/local-credential-helper.mts index 3e4e60e2c83..5d3bdacabb1 100755 --- a/scripts/local-credential-helper.mts +++ b/scripts/local-credential-helper.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/openclaw/patch-gateway-daemon-dialback.mts b/scripts/openclaw/patch-gateway-daemon-dialback.mts index a6b2040e7da..2a142d43de6 100755 --- a/scripts/openclaw/patch-gateway-daemon-dialback.mts +++ b/scripts/openclaw/patch-gateway-daemon-dialback.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-bundled-npm-brace-expansion.mts b/scripts/patch-bundled-npm-brace-expansion.mts index b91b7c42234..d2a18a2d693 100755 --- a/scripts/patch-bundled-npm-brace-expansion.mts +++ b/scripts/patch-bundled-npm-brace-expansion.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-bundled-npm-tar.mts b/scripts/patch-bundled-npm-tar.mts index fb054cd4177..76ff1fd8449 100755 --- a/scripts/patch-bundled-npm-tar.mts +++ b/scripts/patch-bundled-npm-tar.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-chat-send.mts b/scripts/patch-openclaw-chat-send.mts index 939f529c545..d01d29eacc6 100755 --- a/scripts/patch-openclaw-chat-send.mts +++ b/scripts/patch-openclaw-chat-send.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-issue-4434-diagnostics.mts b/scripts/patch-openclaw-issue-4434-diagnostics.mts index 6b49acdd2ab..fbfee656785 100755 --- a/scripts/patch-openclaw-issue-4434-diagnostics.mts +++ b/scripts/patch-openclaw-issue-4434-diagnostics.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-managed-transport-diagnostics.mts b/scripts/patch-openclaw-managed-transport-diagnostics.mts index e0963bdbaab..4a11f9f43fc 100755 --- a/scripts/patch-openclaw-managed-transport-diagnostics.mts +++ b/scripts/patch-openclaw-managed-transport-diagnostics.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-mcp-npx.mts b/scripts/patch-openclaw-mcp-npx.mts index ba30ee68eb8..a7f0291b229 100755 --- a/scripts/patch-openclaw-mcp-npx.mts +++ b/scripts/patch-openclaw-mcp-npx.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-mcp-reliability.mts b/scripts/patch-openclaw-mcp-reliability.mts index 171e0d5520b..cd5fae97484 100755 --- a/scripts/patch-openclaw-mcp-reliability.mts +++ b/scripts/patch-openclaw-mcp-reliability.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-mcp-tools-list-timeout.mts b/scripts/patch-openclaw-mcp-tools-list-timeout.mts index aa07428233f..defb323da2e 100755 --- a/scripts/patch-openclaw-mcp-tools-list-timeout.mts +++ b/scripts/patch-openclaw-mcp-tools-list-timeout.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-shared-state-permissions.mts b/scripts/patch-openclaw-shared-state-permissions.mts index 470f5355afc..8a45dfef6d5 100755 --- a/scripts/patch-openclaw-shared-state-permissions.mts +++ b/scripts/patch-openclaw-shared-state-permissions.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/patch-openclaw-tool-catalog.mts b/scripts/patch-openclaw-tool-catalog.mts index e5b1b14d738..9088474cb8a 100755 --- a/scripts/patch-openclaw-tool-catalog.mts +++ b/scripts/patch-openclaw-tool-catalog.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/prepare-dual-dgx-station.mts b/scripts/prepare-dual-dgx-station.mts index 65ef12b7300..2d218f26169 100755 --- a/scripts/prepare-dual-dgx-station.mts +++ b/scripts/prepare-dual-dgx-station.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --no-warnings --experimental-strip-types +#!/usr/bin/env -S node --no-warnings // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/retire-release-label.mts b/scripts/retire-release-label.mts index e33710233ee..27cdf83cede 100644 --- a/scripts/retire-release-label.mts +++ b/scripts/retire-release-label.mts @@ -9,7 +9,7 @@ * Run only inside the release-latest-tag workflow, which serializes this * operation with every authorized release-label assignment. * - * Usage: node --experimental-strip-types --no-warnings scripts/retire-release-label.mts [--repo OWNER/REPO] + * Usage: node --no-warnings scripts/retire-release-label.mts [--repo OWNER/REPO] */ import { execFileSync } from "node:child_process"; diff --git a/scripts/shellcheck-json1-to-sarif.mts b/scripts/shellcheck-json1-to-sarif.mts index 0775abf0b07..b9cca0d0c39 100644 --- a/scripts/shellcheck-json1-to-sarif.mts +++ b/scripts/shellcheck-json1-to-sarif.mts @@ -192,7 +192,7 @@ function formatError(error: unknown): string { function usage(): string { return ( - "Usage: node --experimental-strip-types scripts/shellcheck-json1-to-sarif.mts " + + "Usage: node scripts/shellcheck-json1-to-sarif.mts " + " " ); } diff --git a/scripts/update-hermes-agent.sh b/scripts/update-hermes-agent.sh index 6b3f96f918c..9617a6fa447 100755 --- a/scripts/update-hermes-agent.sh +++ b/scripts/update-hermes-agent.sh @@ -203,7 +203,7 @@ installed_copy_schema_error() { "hermes-mcp-config-transaction.py" \ "openshell-child-visible-credentials.v0.0.106.json" \ "HERMES_HOME=/sandbox/.hermes /usr/local/bin/hermes doctor --fix" \ - "node --experimental-strip-types /opt/nemoclaw-hermes-config/generate-config.ts" \ + "node /opt/nemoclaw-hermes-config/generate-config.ts" \ "/sandbox/.hermes/profiles/dashboard-home"; do grep -Fq "$item" "$dockerfile" || missing+=("marker ${item}") done diff --git a/scripts/upgrade-bundled-npm.mts b/scripts/upgrade-bundled-npm.mts index 913a53fe9c6..972c5c5bac1 100755 --- a/scripts/upgrade-bundled-npm.mts +++ b/scripts/upgrade-bundled-npm.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/scripts/validate-openclaw-tool-search.mts b/scripts/validate-openclaw-tool-search.mts index 116d68a3461..da4abee4ede 100755 --- a/scripts/validate-openclaw-tool-search.mts +++ b/scripts/validate-openclaw-tool-search.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/src/lib/actions/uninstall/bedrock-runtime-adapter-cleanup.test.ts b/src/lib/actions/uninstall/bedrock-runtime-adapter-cleanup.test.ts index 4106aecab0a..ae0cee260c5 100644 --- a/src/lib/actions/uninstall/bedrock-runtime-adapter-cleanup.test.ts +++ b/src/lib/actions/uninstall/bedrock-runtime-adapter-cleanup.test.ts @@ -143,7 +143,7 @@ function writeJournal( function managedProcess(overrides: Partial = {}): AdapterProcess { return { - argv: [EXECUTABLE_PATH, "--experimental-strip-types", "--no-warnings", SCRIPT_PATH], + argv: [EXECUTABLE_PATH, "--no-warnings", SCRIPT_PATH], executablePath: EXECUTABLE_PATH, generation: GENERATION, processStart: PROCESS_START, @@ -434,7 +434,6 @@ describe("Bedrock Runtime adapter fail-closed uninstall cleanup (#9552)", () => process: managedProcess({ argv: [ EXECUTABLE_PATH, - "--experimental-strip-types", "--no-warnings", "/tmp/foreign/bedrock-runtime-adapter.mts", ], diff --git a/src/lib/hermes-tool-gateway-broker.ts b/src/lib/hermes-tool-gateway-broker.ts index 9d960929d32..ede11194805 100644 --- a/src/lib/hermes-tool-gateway-broker.ts +++ b/src/lib/hermes-tool-gateway-broker.ts @@ -493,7 +493,7 @@ function probeHermesToolGatewayBrokerStart(options = {}) { try { const result = spawnProbe( process.execPath, - ["--experimental-strip-types", HERMES_TOOL_GATEWAY_SCRIPT], + [HERMES_TOOL_GATEWAY_SCRIPT], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], @@ -732,7 +732,7 @@ function spawnHermesToolGatewayBroker(refreshToken, initialSandboxName = null) { } const child = spawn( process.execPath, - ["--experimental-strip-types", HERMES_TOOL_GATEWAY_SCRIPT], + [HERMES_TOOL_GATEWAY_SCRIPT], { detached: true, stdio: "ignore", diff --git a/src/lib/inference/bedrock-runtime-adapter.test.ts b/src/lib/inference/bedrock-runtime-adapter.test.ts index 690d964d4e4..026083d0a33 100644 --- a/src/lib/inference/bedrock-runtime-adapter.test.ts +++ b/src/lib/inference/bedrock-runtime-adapter.test.ts @@ -648,7 +648,7 @@ describe("Bedrock Runtime OpenAI adapter", () => { }); vi.mocked(readLocalAdapterTextFile).mockReturnValueOnce(token).mockReturnValueOnce("4242"); runCaptureMock.mockReturnValueOnce( - `${process.execPath} --experimental-strip-types --no-warnings ${__test.getAdapterScriptPath()}`, + `${process.execPath} --no-warnings ${__test.getAdapterScriptPath()}`, ); await expect( @@ -683,7 +683,7 @@ describe("Bedrock Runtime OpenAI adapter", () => { }); vi.mocked(readLocalAdapterTextFile).mockReturnValueOnce(token).mockReturnValueOnce("4242"); runCaptureMock.mockReturnValueOnce( - `${process.execPath} --experimental-strip-types --no-warnings ${__test.getAdapterScriptPath()}`, + `${process.execPath} --no-warnings ${__test.getAdapterScriptPath()}`, ); await expect( @@ -719,7 +719,7 @@ describe("Bedrock Runtime OpenAI adapter", () => { vi.mocked(readLocalAdapterJsonFile).mockReturnValueOnce(priorState); vi.mocked(readLocalAdapterTextFile).mockReturnValueOnce(token).mockReturnValueOnce("4242"); runCaptureMock.mockReturnValueOnce( - `${process.execPath} --experimental-strip-types --no-warnings ${__test.getAdapterScriptPath()}`, + `${process.execPath} --no-warnings ${__test.getAdapterScriptPath()}`, ); vi.mocked(probeLocalAdapterHealth).mockResolvedValueOnce(false).mockResolvedValueOnce(true); vi.mocked(waitForLocalAdapterHealth).mockImplementationOnce(async (probe, options) => { @@ -764,7 +764,7 @@ describe("Bedrock Runtime OpenAI adapter", () => { }); vi.mocked(readLocalAdapterTextFile).mockReturnValueOnce(token).mockReturnValueOnce("4242"); runCaptureMock.mockReturnValueOnce( - `${process.execPath} --experimental-strip-types --no-warnings ${__test.getAdapterScriptPath()}`, + `${process.execPath} --no-warnings ${__test.getAdapterScriptPath()}`, ); vi.mocked(waitForLocalAdapterHealth).mockResolvedValueOnce(true); vi.mocked(observeBedrockRuntimeAdapterProcess).mockReturnValueOnce(null); diff --git a/src/lib/inference/local-adapter-lifecycle.ts b/src/lib/inference/local-adapter-lifecycle.ts index ae5fda2aca2..d9f3dde3beb 100644 --- a/src/lib/inference/local-adapter-lifecycle.ts +++ b/src/lib/inference/local-adapter-lifecycle.ts @@ -254,7 +254,7 @@ export function spawnDetachedNodeAdapter(options: { }): ChildProcess { const child = spawn( process.execPath, - ["--experimental-strip-types", "--no-warnings", options.scriptPath], + ["--no-warnings", options.scriptPath], { detached: true, stdio: "ignore", diff --git a/src/lib/messaging/applier/build/messaging-build-applier.mts b/src/lib/messaging/applier/build/messaging-build-applier.mts index 81ae2d3f827..5399f11e2d9 100755 --- a/src/lib/messaging/applier/build/messaging-build-applier.mts +++ b/src/lib/messaging/applier/build/messaging-build-applier.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 @@ -791,7 +791,6 @@ function installOpenClawPluginPackages(installs: readonly OpenClawPluginInstall[ runCommand( [ "node", - "--experimental-strip-types", install.runtimeLock.verifierPath, install.runtimeLock.lockFile, install.runtimeLock.projectsRoot, diff --git a/src/lib/messaging/post-agent-install-selection.test.ts b/src/lib/messaging/post-agent-install-selection.test.ts index 34e8c3b23f9..22892761a68 100644 --- a/src/lib/messaging/post-agent-install-selection.test.ts +++ b/src/lib/messaging/post-agent-install-selection.test.ts @@ -85,7 +85,6 @@ describe("post-agent-install messaging selection", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", `import(${JSON.stringify(moduleUrl)})`, diff --git a/src/lib/onboard/dockerfile-remote-dashboard-bind-contract.ts b/src/lib/onboard/dockerfile-remote-dashboard-bind-contract.ts index 83a887c73af..04a945293eb 100644 --- a/src/lib/onboard/dockerfile-remote-dashboard-bind-contract.ts +++ b/src/lib/onboard/dockerfile-remote-dashboard-bind-contract.ts @@ -13,15 +13,15 @@ const REMOTE_BIND_ARG_RE = /^ARG\s+NEMOCLAW_DASHBOARD_BIND=/; const REMOTE_BIND_PATCHED_ARG_RE = /^ARG\s+NEMOCLAW_DASHBOARD_BIND=0\.0\.0\.0$/; const REMOTE_BIND_PROMOTION_RE = /NEMOCLAW_DASHBOARD_BIND=\$\{NEMOCLAW_DASHBOARD_BIND\}/; const OPENCLAW_CONFIG_GENERATOR_RE = - /^RUN\s+(?:NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0\s+)?(?:NEMOCLAW_OPENCLAW_MANAGED_PROXY=0\s+)?node\s+--experimental-strip-types\s+\/scripts\/generate-openclaw-config\.mts$/; + /^RUN\s+(?:NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0\s+)?(?:NEMOCLAW_OPENCLAW_MANAGED_PROXY=0\s+)?node\s+\/scripts\/generate-openclaw-config\.mts$/; const SAFE_VALIDATION_GENERATOR_RE = - /^RUN\s+validation_home="\$validation_root\/progressive";\s+HOME=(?:"\$validation_home"|\$validation_home)\s+node\s+--experimental-strip-types\s+\/scripts\/generate-openclaw-config\.mts$/; + /^RUN\s+validation_home="\$validation_root\/progressive";\s+HOME=(?:"\$validation_home"|\$validation_home)\s+node\s+\/scripts\/generate-openclaw-config\.mts$/; const PASSIVE_FINAL_STAGE_INSTRUCTION_RE = /^(?:ARG|ENV|WORKDIR|USER|HEALTHCHECK|ENTRYPOINT|CMD)\b/; const CONFIG_MODE_RE = /^RUN\s+chmod\s+660\s+\/sandbox\/\.openclaw\/openclaw\.json$/; const CONFIG_HASH_RE = /^RUN\s+sha256sum\s+\/sandbox\/\.openclaw\/openclaw\.json\s+>\s+\/sandbox\/\.openclaw\/\.config-hash(?:\s+&&\s+chmod\s+660\s+\/sandbox\/\.openclaw\/\.config-hash)?(?:\s+&&\s+chown\s+sandbox:sandbox\s+\/sandbox\/\.openclaw\/\.config-hash)?$/; const MESSAGING_BUILD_APPLIER_RE = - /^RUN\s+OPENCLAW_VERSION="\$\{OPENCLAW_VERSION\}"\s+node\s+--experimental-strip-types\s+\/src\/lib\/messaging\/applier\/build\/messaging-build-applier\.mts\s+--agent\s+openclaw\s+--phase\s+(?:agent-install|post-agent-install)$/; + /^RUN\s+OPENCLAW_VERSION="\$\{OPENCLAW_VERSION\}"\s+node\s+\/src\/lib\/messaging\/applier\/build\/messaging-build-applier\.mts\s+--agent\s+openclaw\s+--phase\s+(?:agent-install|post-agent-install)$/; const EXACT_CUSTOM_POST_GENERATOR_RUN_RE = [ CONFIG_MODE_RE, CONFIG_HASH_RE, @@ -34,7 +34,7 @@ const EXACT_CUSTOM_POST_GENERATOR_RUN_RE = [ // openclaw.json>` to an otherwise safe command. A lifecycle test verifies // these digests against the checked-in Dockerfile. const CANONICAL_POST_GENERATOR_INSTRUCTION_SHA256 = new Set([ - "9300de0b56a7d8a1498fd36cb9c05313b6691d6756b455f91628ed989221afc2", + "d0ed2268f42964e8a150deb39e68e31313e520503fa2c131a4d7cc8b21191da0", "6f457f365f5c0d128e5e3b549a630b5bd9ebd223919f2c2c8e6a31235d763781", "dca7d3dbc030e4efa77c850b9d21a826358c69c7d2062f3eee2f5a57eeb07aa2", "b01b5f5d2cba5778cd8eb87139f2c6a8174082a7f6775e443a1dbdc0629ce7e5", @@ -43,8 +43,8 @@ const CANONICAL_POST_GENERATOR_INSTRUCTION_SHA256 = new Set([ "4e548aafe9484a887a0ab0cf92ec82f77843fd346de7a2dff50b93ebd632b044", "737edaaa69f80cf10d42fd349e0be068c1ef6e7375d5dcb4055b012420b58736", "5b814e92449a6778385f588877fe72ebed80e601f8eb0c90c2842b17a489f3da", - "0e1a9a7bab2fab0a974577c3af8785157b4b9be2b4db32d5f4f9e5aa3c8c8171", - "ede14966118316b58139830b4a1ffaceca86a6d0857cd0c1705d69db109907b0", + "7c2cf32df8b7ad57a7bc155707df0dd706dd74fe640d726df25f9b8c4d150a90", + "71abf445c5919eb84d25c3d15fc70ddf71b02eb7e22177794d425e295bb14e5e", "a68297161e2c6463440b822f4e4be0518e745fb5fba8c61ab53b876724f7b666", "a54e2ac58ef00d7080ad697cb1892bf91b7bffe011f698df17b936c9906cd4af", "ca493ae7905fae5c587a8e5c31fcb3d423235940589c2decee99d7b338e87d88", @@ -65,8 +65,8 @@ const CANONICAL_POST_GENERATOR_INSTRUCTION_SHA256 = new Set([ "4165899eb1f0f948f8883eddf4136136caac21cee1df39b12afea7672b23a378", "7e6a6879382f833f17be02ca7d287685b6afa1c423b1e087b3b05dd677d6e325", "4a54da2c1c33c681ae0dad181a5a7456c926051d91420aa60cf7edef6330ba65", - "e958e532c3e770fa426a6662652dbde2ddaeb41a214ccffe2def5a43a8b5b023", - "c6894538ce0c377566a22b11af9682a9952bfd936fd4d011f6f50da30c8e875e", + "e69b86c132e44c502b3dce8b9359c8798079e93489bd2d27f75d514b45502d4e", + "d4b6c80ecc6f243f2141a439e2690aa563c55e19e7d6f3965d3d8685507866c1", "e1b6dca3e6b30624f364b36ff52e654978bc120cc7800df2ff209c14949acd64", "c682148fc7efec9f947c326c6029181cd879b7cba3e8361246aba7d0e6fe70a3", "2801e488822e10a39a5586bd150279e54df4612e30c2fa782453534a466def59", @@ -74,7 +74,7 @@ const CANONICAL_POST_GENERATOR_INSTRUCTION_SHA256 = new Set([ // Reviewed late messaging inputs, metadata setup, and runtime assertions. "7e5f7e1dfb90e5e4b863afdfb9ba58e57e3693bdc6f47ac8c13e80bdc9eff56b", "8f5966da093ef75cefd35c2b7f1361fbf5b32e63a4a8a34cb3ac7f76a1330e5e", - "c6b042ac2cc3d5570ae43f1e387a951cbe89fbb22e8cd9df486f99719bb32939", + "4c2f29cb433ff14ca386e71373b53e88c705e2ed255b435715681a0dd64e43f9", "761ea4fbb0da5cf3390ee8f2e56f3703a7da88c96ac47fea89d0fff800f728ae", "bda3ce8d453fa143943eac44bea4288e44a3cdbf5e9e54a3da68154f06d08c3d", // COPY --from=openclaw-runtime-payload / / diff --git a/src/lib/onboard/managed-startup-image-runtime.test.ts b/src/lib/onboard/managed-startup-image-runtime.test.ts index 1a938a3d195..f3088720af7 100644 --- a/src/lib/onboard/managed-startup-image-runtime.test.ts +++ b/src/lib/onboard/managed-startup-image-runtime.test.ts @@ -154,7 +154,6 @@ describe("buildManagedStartupImageActionPlan", () => { runAs: "sandbox", argv: [ "/usr/local/bin/node", - "--experimental-strip-types", "/opt/nemoclaw-deepagents-code/generate-config.ts", ], }, diff --git a/src/lib/onboard/managed-startup/image-runtime.ts b/src/lib/onboard/managed-startup/image-runtime.ts index 5a603f55ebf..14d68b7cabc 100644 --- a/src/lib/onboard/managed-startup/image-runtime.ts +++ b/src/lib/onboard/managed-startup/image-runtime.ts @@ -522,25 +522,21 @@ function generatorCommand(agent: ManagedStartupAgent): readonly string[] { case "openclaw": return [ "/usr/local/bin/node", - "--experimental-strip-types", "/scripts/generate-openclaw-config.mts", ]; case "hermes": return [ "/usr/local/bin/node", - "--experimental-strip-types", "/opt/nemoclaw-hermes-config/generate-config.ts", ]; case "langchain-deepagents-code": return [ "/usr/local/bin/node", - "--experimental-strip-types", "/opt/nemoclaw-deepagents-code/generate-config.ts", ]; case "pi": return [ "/usr/local/bin/node", - "--experimental-strip-types", "/opt/nemoclaw-pi/generate-config.ts", ]; } @@ -553,7 +549,6 @@ function messagingCommand( ): readonly string[] { return [ "/usr/local/bin/node", - "--experimental-strip-types", "/src/lib/messaging/applier/build/messaging-build-applier.mts", "--agent", agent, diff --git a/test/agents/deepagents/langchain-deepagents-code-config.test.ts b/test/agents/deepagents/langchain-deepagents-code-config.test.ts index 7ed70b40dd8..2e935c454a1 100644 --- a/test/agents/deepagents/langchain-deepagents-code-config.test.ts +++ b/test/agents/deepagents/langchain-deepagents-code-config.test.ts @@ -52,7 +52,7 @@ function runGeneratorProcess( .filter(([, value]) => value === undefined) .forEach(([name]) => Reflect.deleteProperty(childEnv, name)); return { - ...spawnSync(process.execPath, ["--experimental-strip-types", script], { + ...spawnSync(process.execPath, [script], { cwd: process.cwd(), encoding: "utf8", env: childEnv, diff --git a/test/agents/deepagents/langchain-deepagents-code-image.test.ts b/test/agents/deepagents/langchain-deepagents-code-image.test.ts index bfa342a4abe..6fc52de41a3 100644 --- a/test/agents/deepagents/langchain-deepagents-code-image.test.ts +++ b/test/agents/deepagents/langchain-deepagents-code-image.test.ts @@ -235,7 +235,7 @@ describe("LangChain Deep Agents Code image contracts", () => { "COPY src/lib/inference/managed-dcode/identity.ts /opt/nemoclaw-deepagents-code/src/lib/inference/managed-dcode/identity.ts", ); expect(dockerfile).toContain( - "node --experimental-strip-types /opt/nemoclaw-deepagents-code/generate-config.ts", + "node /opt/nemoclaw-deepagents-code/generate-config.ts", ); expect(dockerfile).not.toContain("langchain-deepagents-code-sandbox-base:latest"); expect(dockerfile).toContain( diff --git a/test/agents/deepagents/langchain-deepagents-code-provider-label.test.ts b/test/agents/deepagents/langchain-deepagents-code-provider-label.test.ts index ca980af3744..e955228086d 100644 --- a/test/agents/deepagents/langchain-deepagents-code-provider-label.test.ts +++ b/test/agents/deepagents/langchain-deepagents-code-provider-label.test.ts @@ -57,7 +57,7 @@ describe("LangChain Deep Agents Code managed provider label", () => { "langchain-deepagents-code", "generate-config.ts", ); - execFileSync(process.execPath, ["--experimental-strip-types", generator], { + execFileSync(process.execPath, [generator], { env: { PATH: process.env.PATH, HOME: tempDir, diff --git a/test/agents/hermes/hermes-image-build-probes.test.ts b/test/agents/hermes/hermes-image-build-probes.test.ts index 013bde1a97b..d008619dafd 100644 --- a/test/agents/hermes/hermes-image-build-probes.test.ts +++ b/test/agents/hermes/hermes-image-build-probes.test.ts @@ -107,7 +107,8 @@ exit ${doctorExit} node, `#!/usr/bin/env bash set -euo pipefail -test "$1" = "--experimental-strip-types" +test "$#" -eq 1 +test "$1" = "${generator}" printf 'generate\n' >> "$ORDER_LOG" printf 'model: trusted\n' > "$HERMES_HOME/config.yaml" printf 'SAFE=1\n' > "$HERMES_HOME/.env" diff --git a/test/agents/hermes/hermes-runtime-api-key.test.ts b/test/agents/hermes/hermes-runtime-api-key.test.ts index cbb198a939c..7900472caf5 100644 --- a/test/agents/hermes/hermes-runtime-api-key.test.ts +++ b/test/agents/hermes/hermes-runtime-api-key.test.ts @@ -280,8 +280,8 @@ function runHermesDockerfileRuntimePlanGuard(runtimePlan: unknown) { "# Apply messaging agent-install hooks", ) .replace( - "node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase runtime-setup", - `node --experimental-strip-types ${shellQuote(applierPath)}`, + "node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent hermes --phase runtime-setup", + `node ${shellQuote(applierPath)}`, ) .replaceAll("/usr/local/share/nemoclaw/messaging-runtime-plan.json", runtimePlanPath) // Unit fixtures run as the invoking user, not Docker root; keep the diff --git a/test/agents/hermes/hermes-tool-gateway-broker.test.ts b/test/agents/hermes/hermes-tool-gateway-broker.test.ts index ca28470b2c6..4cbabfaed13 100644 --- a/test/agents/hermes/hermes-tool-gateway-broker.test.ts +++ b/test/agents/hermes/hermes-tool-gateway-broker.test.ts @@ -1014,7 +1014,7 @@ describe("Hermes managed-tool gateway broker", () => { const brokerPort = await freePort(); const child = resources.ownChild( - spawn(process.execPath, ["--experimental-strip-types", SCRIPT], { + spawn(process.execPath, [SCRIPT], { env: { ...process.env, HERMES_TOOL_GATEWAY_PORT: String(brokerPort), @@ -1264,7 +1264,7 @@ describe("Hermes managed-tool gateway broker", () => { ); const brokerPort = await freePort(); const child = resources.ownChild( - spawn(process.execPath, ["--experimental-strip-types", SCRIPT], { + spawn(process.execPath, [SCRIPT], { env: { ...process.env, HERMES_TOOL_GATEWAY_PORT: String(brokerPort), diff --git a/test/agents/openclaw/openclaw-dependency-review.test.ts b/test/agents/openclaw/openclaw-dependency-review.test.ts index 933c8f14aa3..f0ead664142 100644 --- a/test/agents/openclaw/openclaw-dependency-review.test.ts +++ b/test/agents/openclaw/openclaw-dependency-review.test.ts @@ -275,16 +275,16 @@ check_not_contains "$optional_plugin_block" 'pack_reviewed_npm_tarball' "optiona grep -Fq 'OPENSHELL_SANDBOX !== "1"' "$issue_4434_patch" grep -Fq 'nemoclaw: #4434 structured unreachable-inference diagnostic' "$issue_4434_patch" grep -Fq 'COPY scripts/patch-openclaw-issue-4434-diagnostics.mts /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-issue-4434-diagnostics.mts \\' Dockerfile grep -Fq 'COPY scripts/patch-openclaw-tool-catalog.mts /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-tool-catalog.mts \\' Dockerfile ! grep -Fq 'patch-openclaw-tool-catalog.js' Dockerfile device_self_approval_patch=${JSON.stringify(DEVICE_SELF_APPROVAL_PATCH)} grep -Fq 'nemoclaw: reach gateway for bounded same-device scope approval' "$device_self_approval_patch" grep -Fq 'nemoclaw: bounded same-device scope approval' "$device_self_approval_patch" grep -Fq 'nemoclaw: validate bounded self-approval inside pairing lock' "$device_self_approval_patch" grep -Fq 'COPY scripts/patch-openclaw-device-self-approval.mts /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-device-self-approval.mts \\' Dockerfile shared_state_permissions_patch=${JSON.stringify(SHARED_STATE_PERMISSIONS_PATCH)} grep -Fq 'nemoclaw: group-shared OpenClaw state' "$shared_state_permissions_patch" grep -Fq 'nemoclaw: group-shared OpenClaw agent state' "$shared_state_permissions_patch" @@ -294,20 +294,20 @@ check_not_contains "$optional_plugin_block" 'pack_reviewed_npm_tarball' "optiona grep -Fq 'nemoclaw: group-shared OpenClaw models file' "$shared_state_permissions_patch" grep -Fq 'nemoclaw: ignore legacy OpenClaw update-check state' "$shared_state_permissions_patch" grep -Fq 'COPY scripts/patch-openclaw-shared-state-permissions.mts /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-shared-state-permissions.mts \\' Dockerfile mcp_reliability_patch=${JSON.stringify(MCP_RELIABILITY_PATCH)} grep -Fq 'nemoclaw mcp transient startup recovery (#7958)' "$mcp_reliability_patch" grep -Fq 'nemoClawIsTransientMcpStartFailure' "$mcp_reliability_patch" grep -Fq 'nemoClawCatalogHasStartDiagnostics' "$mcp_reliability_patch" grep -Fq 'COPY scripts/patch-openclaw-mcp-reliability.mts /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-mcp-reliability.mts \\' Dockerfile ! grep -Fq 'patch-openclaw-mcp-reliability.js' Dockerfile mcp_tools_list_timeout_patch=${JSON.stringify(MCP_TOOLS_LIST_TIMEOUT_PATCH)} grep -Fq 'NEMOCLAW_MCP_TOOLS_LIST_TIMEOUT_MS' "$mcp_tools_list_timeout_patch" grep -Fq 'TOOLS_LIST_TIMEOUT_MIN_MS = 1500' "$mcp_tools_list_timeout_patch" grep -Fq 'TOOLS_LIST_TIMEOUT_MAX_MS = 10_000' "$mcp_tools_list_timeout_patch" grep -Fq 'COPY scripts/patch-openclaw-mcp-tools-list-timeout.mts /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts' Dockerfile - grep -Fq 'node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts \\' Dockerfile + grep -Fq 'node /usr/local/lib/nemoclaw/patch-openclaw-mcp-tools-list-timeout.mts \\' Dockerfile ! grep -Fq 'patch-openclaw-mcp-tools-list-timeout.js' Dockerfile phase_count="$(grep -Ec -- '--phase (runtime-setup|agent-install|post-agent-install)' Dockerfile)" diff --git a/test/agents/openclaw/openclaw-gateway-daemon-dialback-patch.test.ts b/test/agents/openclaw/openclaw-gateway-daemon-dialback-patch.test.ts index 9dacd003a03..423f35fce51 100644 --- a/test/agents/openclaw/openclaw-gateway-daemon-dialback-patch.test.ts +++ b/test/agents/openclaw/openclaw-gateway-daemon-dialback-patch.test.ts @@ -90,7 +90,7 @@ function readGatewayDaemonDialbackBuildCommand(): string { const newline = String.fromCharCode(10); const expectedBlock = [ `RUN if [ "$OPENCLAW_VERSION" = "2026.7.1" ]; then ${continuation}`, - ` node --experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts ${continuation}`, + ` node /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts ${continuation}`, ` /usr/local/lib/node_modules/openclaw/dist; ${continuation}`, " fi", ].join(newline); @@ -109,7 +109,7 @@ describe("OpenClaw gateway daemon self-dialback patch", () => { { expectedCalls: "", version: "2026.4.24" }, { expectedCalls: - "--experimental-strip-types /usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts /usr/local/lib/node_modules/openclaw/dist\n", + "/usr/local/lib/nemoclaw/patch-openclaw-gateway-daemon-dialback.mts /usr/local/lib/node_modules/openclaw/dist\n", version: "2026.7.1", }, ])( @@ -347,7 +347,7 @@ describe("OpenClaw gateway daemon self-dialback patch", () => { fs.writeFileSync(path.join(tmp, "connection-details.js"), CONNECTION_DETAILS_SOURCE); fs.writeFileSync(path.join(tmp, "gateway-tools.js"), TOOL_TARGET_SOURCE); - const apply = spawnSync(process.execPath, ["--experimental-strip-types", PATCH_SCRIPT, tmp], { + const apply = spawnSync(process.execPath, [PATCH_SCRIPT, tmp], { encoding: "utf8", }); expect(apply.status, apply.stderr).toBe(0); @@ -355,7 +355,7 @@ describe("OpenClaw gateway daemon self-dialback patch", () => { const audit = spawnSync( process.execPath, - ["--experimental-strip-types", PATCH_SCRIPT, "--audit", tmp], + [PATCH_SCRIPT, "--audit", tmp], { encoding: "utf8" }, ); expect(audit.status, audit.stderr).toBe(0); diff --git a/test/agents/openclaw/openclaw-issue-4434-diagnostics-patch.test.ts b/test/agents/openclaw/openclaw-issue-4434-diagnostics-patch.test.ts index f7595946a66..4f28bb92896 100644 --- a/test/agents/openclaw/openclaw-issue-4434-diagnostics-patch.test.ts +++ b/test/agents/openclaw/openclaw-issue-4434-diagnostics-patch.test.ts @@ -89,7 +89,7 @@ function writeRenamedArrowAssistantFormatterFixture(dist: string): string { } function runPatch(dist: string, args: string[] = []) { - return spawnSync(process.execPath, ["--experimental-strip-types", PATCH_SCRIPT, ...args, dist], { + return spawnSync(process.execPath, [PATCH_SCRIPT, ...args, dist], { encoding: "utf-8", timeout: 10000, }); @@ -288,7 +288,7 @@ describe("OpenClaw diagnostics compatibility patch (#4434)", () => { try { const result = spawnSync( process.execPath, - ["--experimental-strip-types", PATCH_SCRIPT, tmp, tmp], + [PATCH_SCRIPT, tmp, tmp], { encoding: "utf-8", timeout: 10000, diff --git a/test/agents/openclaw/openclaw-mcp-npx-patch.test.ts b/test/agents/openclaw/openclaw-mcp-npx-patch.test.ts index c467d51d63d..dabfe1c99ca 100644 --- a/test/agents/openclaw/openclaw-mcp-npx-patch.test.ts +++ b/test/agents/openclaw/openclaw-mcp-npx-patch.test.ts @@ -65,7 +65,7 @@ function writeMcpTransportOnlyFixture(dist: string): string { } function runPatch(dist: string) { - return spawnSync(process.execPath, ["--experimental-strip-types", PATCH_SCRIPT, dist], { + return spawnSync(process.execPath, [PATCH_SCRIPT, dist], { encoding: "utf-8", timeout: 10_000, }); diff --git a/test/agents/openclaw/openclaw-mcp-reliability-patch.test.ts b/test/agents/openclaw/openclaw-mcp-reliability-patch.test.ts index b2d3da484a7..2349c4511bc 100644 --- a/test/agents/openclaw/openclaw-mcp-reliability-patch.test.ts +++ b/test/agents/openclaw/openclaw-mcp-reliability-patch.test.ts @@ -244,7 +244,7 @@ describe("OpenClaw MCP transient startup recovery patch (#7958)", () => { const applied = spawnSync( process.execPath, - ["--experimental-strip-types", PATCH_SCRIPT, dist], + [PATCH_SCRIPT, dist], { encoding: "utf-8", }, @@ -255,7 +255,7 @@ describe("OpenClaw MCP transient startup recovery patch (#7958)", () => { const audited = spawnSync( process.execPath, - ["--experimental-strip-types", PATCH_SCRIPT, "--audit", dist], + [PATCH_SCRIPT, "--audit", dist], { encoding: "utf-8" }, ); expect(audited.status).toBe(0); diff --git a/test/agents/openclaw/openclaw-optional-plugin-build.test.ts b/test/agents/openclaw/openclaw-optional-plugin-build.test.ts index 8e6ec8f7ecf..295125c9f16 100644 --- a/test/agents/openclaw/openclaw-optional-plugin-build.test.ts +++ b/test/agents/openclaw/openclaw-optional-plugin-build.test.ts @@ -153,7 +153,7 @@ it.each([ expect(result.status, result.stderr).toBe(0); expect(calls.trim().split("\n")).toEqual([ - `node --experimental-strip-types /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase ${expectedPhase}`, + `node /src/lib/messaging/applier/build/messaging-build-applier.mts --agent openclaw --phase ${expectedPhase}`, ]); } finally { fs.rmSync(tmp, { recursive: true, force: true }); diff --git a/test/agents/openclaw/openclaw-real-patched-dist-harness.test.ts b/test/agents/openclaw/openclaw-real-patched-dist-harness.test.ts index ea68b070d06..8ff2ccec31b 100644 --- a/test/agents/openclaw/openclaw-real-patched-dist-harness.test.ts +++ b/test/agents/openclaw/openclaw-real-patched-dist-harness.test.ts @@ -476,7 +476,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const chatPatch = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_CHAT_SEND, dist], + [PATCH_OPENCLAW_CHAT_SEND, dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS, @@ -491,7 +491,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const audit = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_CHAT_SEND, "--audit", dist], + [PATCH_OPENCLAW_CHAT_SEND, "--audit", dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS, @@ -525,7 +525,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const issue4434Patch = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_ISSUE_4434_DIAGNOSTICS, dist], + [PATCH_OPENCLAW_ISSUE_4434_DIAGNOSTICS, dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS, @@ -540,7 +540,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const issue4434Audit = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_ISSUE_4434_DIAGNOSTICS, "--audit", dist], + [PATCH_OPENCLAW_ISSUE_4434_DIAGNOSTICS, "--audit", dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS, @@ -560,7 +560,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const gatewayDialbackPatch = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_GATEWAY_DAEMON_DIALBACK, dist], + [PATCH_OPENCLAW_GATEWAY_DAEMON_DIALBACK, dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS }, ); requireSpawnSuccess(gatewayDialbackPatch, "apply gateway daemon self-dialback patch"); @@ -572,7 +572,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const gatewayDialbackAudit = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_GATEWAY_DAEMON_DIALBACK, "--audit", dist], + [PATCH_OPENCLAW_GATEWAY_DAEMON_DIALBACK, "--audit", dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS }, ); requireSpawnSuccess(gatewayDialbackAudit, "audit gateway daemon self-dialback patch"); @@ -610,7 +610,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const sharedStatePatch = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_SHARED_STATE_PERMISSIONS, dist], + [PATCH_OPENCLAW_SHARED_STATE_PERMISSIONS, dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS }, ); requireSpawnSuccess(sharedStatePatch, "apply shared-state permission patch"); @@ -622,7 +622,7 @@ describe.skipIf(process.env.NEMOCLAW_REAL_OPENCLAW_DIST_HARNESS !== "1")( const sharedStateAudit = spawnSync( nodeRuntime.executable, - ["--experimental-strip-types", PATCH_OPENCLAW_SHARED_STATE_PERMISSIONS, dist], + [PATCH_OPENCLAW_SHARED_STATE_PERMISSIONS, dist], { encoding: "utf-8", timeout: PATCH_COMMAND_TIMEOUT_MS }, ); requireSpawnSuccess(sharedStateAudit, "audit shared-state permission patch"); diff --git a/test/agents/openclaw/openclaw-shared-state-permissions-patch.test.ts b/test/agents/openclaw/openclaw-shared-state-permissions-patch.test.ts index 725d1c6a7f4..2e0a5ac5eb5 100644 --- a/test/agents/openclaw/openclaw-shared-state-permissions-patch.test.ts +++ b/test/agents/openclaw/openclaw-shared-state-permissions-patch.test.ts @@ -325,7 +325,7 @@ function makeFixture( } function runPatch(dist: string) { - return spawnSync(process.execPath, ["--experimental-strip-types", PATCH_SCRIPT, dist], { + return spawnSync(process.execPath, [PATCH_SCRIPT, dist], { encoding: "utf8", timeout: 10_000, }); diff --git a/test/agents/openclaw/openclaw-tool-catalog-patch.test.ts b/test/agents/openclaw/openclaw-tool-catalog-patch.test.ts index d8cd2834fc7..f8968012f79 100644 --- a/test/agents/openclaw/openclaw-tool-catalog-patch.test.ts +++ b/test/agents/openclaw/openclaw-tool-catalog-patch.test.ts @@ -158,7 +158,7 @@ function makeFixture(opts: { version?: string; allCustomToolsLine?: string } = { } function runPatch(dist: string) { - return spawnSync(process.execPath, ["--experimental-strip-types", PATCH_SCRIPT, dist], { + return spawnSync(process.execPath, [PATCH_SCRIPT, dist], { encoding: "utf-8", timeout: 10_000, }); diff --git a/test/agents/openclaw/runtime/pi-candidate-runtime-artifacts.test.ts b/test/agents/openclaw/runtime/pi-candidate-runtime-artifacts.test.ts index 514dd96820b..ae549e72837 100644 --- a/test/agents/openclaw/runtime/pi-candidate-runtime-artifacts.test.ts +++ b/test/agents/openclaw/runtime/pi-candidate-runtime-artifacts.test.ts @@ -81,7 +81,7 @@ describe("Pi managed model catalog generation", () => { const home = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-pi-config-")); const result = spawnSync( process.execPath, - ["--experimental-strip-types", path.join(root, "agents/pi/generate-config.ts")], + [path.join(root, "agents/pi/generate-config.ts")], { cwd: root, encoding: "utf8", diff --git a/test/automation/classify-ci-failure.test.ts b/test/automation/classify-ci-failure.test.ts index 5dcbe0cbbe7..39fd1213192 100644 --- a/test/automation/classify-ci-failure.test.ts +++ b/test/automation/classify-ci-failure.test.ts @@ -145,7 +145,6 @@ function fixture(log: string, result?: Record, archive?: Buffer return { root, env }; } const classifierArgs = (extra: string[] = []) => [ - "--experimental-strip-types", "--no-warnings", script, "--job-id", @@ -170,7 +169,6 @@ function importedClassifierArgs(env: NodeJS.ProcessEnv, extra: string[]): string ...(clipMode === undefined ? {} : { clipMode }), }; return [ - "--experimental-strip-types", "--no-warnings", "--input-type=module", "-e", diff --git a/test/automation/e2e/e2e-private-file.test.ts b/test/automation/e2e/e2e-private-file.test.ts index cac51166570..3bc558a0368 100644 --- a/test/automation/e2e/e2e-private-file.test.ts +++ b/test/automation/e2e/e2e-private-file.test.ts @@ -60,7 +60,6 @@ describe("private E2E controller files", () => { const read = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", `import { readPrivateRegularFile } from ${JSON.stringify(moduleUrl)}; readPrivateRegularFile(${JSON.stringify(fifo)}, { maxBytes: 64 });`, @@ -70,7 +69,6 @@ describe("private E2E controller files", () => { const write = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", `import { writePrivateRegularFile } from ${JSON.stringify(moduleUrl)}; writePrivateRegularFile(${JSON.stringify(fifo)}, "replaced\\n");`, @@ -87,7 +85,7 @@ describe("private E2E controller files", () => { expect(write.stderr).toContain(`open '${fifo}'`); const output = ({ read: read.stderr, write: write.stderr } as const)[scenario]!; expect(output).not.toMatch( - /ERR_(?:MODULE_NOT_FOUND|UNKNOWN_FILE_EXTENSION|UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING)|Cannot find module|Unknown file extension|bad option: --experimental-strip-types|SyntaxError/u, + /ERR_(?:MODULE_NOT_FOUND|UNKNOWN_FILE_EXTENSION|UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING)|Cannot find module|Unknown file extension|bad option:|SyntaxError/u, ); expect(fs.lstatSync(fifo).isFIFO()).toBe(true); diff --git a/test/automation/e2e/e2e-recommendations.test.ts b/test/automation/e2e/e2e-recommendations.test.ts index a89beeb7ecc..3e4df51d9b9 100644 --- a/test/automation/e2e/e2e-recommendations.test.ts +++ b/test/automation/e2e/e2e-recommendations.test.ts @@ -153,7 +153,7 @@ describe("E2E recommendation normalizer", () => { const script = `const module = await import(${JSON.stringify(moduleUrl)}); const inventory = module.trustedE2eRecommendationInventory(); if (!inventory.allowedJobIds.includes("onboard-resume") || !inventory.allowedJobIds.includes("vllm-docker-storage")) process.exit(2);`; const result = spawnSync( process.execPath, - ["--experimental-strip-types", "--input-type=module", "--eval", script], + ["--input-type=module", "--eval", script], { cwd: tmp, encoding: "utf8", diff --git a/test/automation/performance/analyze-ci-performance.test.ts b/test/automation/performance/analyze-ci-performance.test.ts index 6461fa93723..9ab1363cb5a 100644 --- a/test/automation/performance/analyze-ci-performance.test.ts +++ b/test/automation/performance/analyze-ci-performance.test.ts @@ -43,7 +43,7 @@ async function runAnalyzer( ): Promise<{ stdout: string; stderr: string }> { return execFileAsync( process.execPath, - ["--experimental-strip-types", "--no-warnings", script, ...args], + ["--no-warnings", script, ...args], { cwd: process.cwd(), env: environment, maxBuffer: 10_000_000 }, ); } diff --git a/test/automation/pull-requests/advisor-http-dispatcher.test.ts b/test/automation/pull-requests/advisor-http-dispatcher.test.ts index 92c7a746223..c618c5b6288 100644 --- a/test/automation/pull-requests/advisor-http-dispatcher.test.ts +++ b/test/automation/pull-requests/advisor-http-dispatcher.test.ts @@ -61,7 +61,7 @@ describe("advisor HTTP dispatcher", () => { `; const child = spawn( process.execPath, - ["--experimental-strip-types", "--no-warnings", "--input-type=module", "--eval", script], + ["--no-warnings", "--input-type=module", "--eval", script], { env: { ...process.env, diff --git a/test/automation/pull-requests/analyze-pr-value-stream.test.ts b/test/automation/pull-requests/analyze-pr-value-stream.test.ts index 4e85c74158c..5d18a8b00c2 100644 --- a/test/automation/pull-requests/analyze-pr-value-stream.test.ts +++ b/test/automation/pull-requests/analyze-pr-value-stream.test.ts @@ -130,7 +130,6 @@ async function run(scenario: string, extra: string[] = []) { const result = await execa( process.execPath, [ - "--experimental-strip-types", "--no-warnings", analyzer, "--workdir", @@ -171,7 +170,7 @@ describe("pull request value-stream analysis", () => { const fake = await fakeGithub("complete"); const result = await execa( process.execPath, - ["--experimental-strip-types", "--no-warnings", analyzer, "--number", "0"], + ["--no-warnings", analyzer, "--number", "0"], { env: { ...process.env, @@ -432,7 +431,6 @@ describe("pull request value-stream analysis", () => { const processResult = execa( process.execPath, [ - "--experimental-strip-types", "--no-warnings", analyzer, "--workdir", diff --git a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts index 6eccb4f5bbe..8dd83d82603 100644 --- a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts +++ b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts @@ -131,7 +131,7 @@ describe("hosted-runner recovery workflow boundary", () => { SOURCE_RUN_ID: "${{ github.event.workflow_run.id }}", }); expect(evaluate.run).toBe( - "node --experimental-strip-types --no-warnings tools/e2e/hosted-runner-recovery.mts", + "node --no-warnings tools/e2e/hosted-runner-recovery.mts", ); }); diff --git a/test/automation/pull-requests/pr-merge-conflict-fixer-workflow-boundary.test.ts b/test/automation/pull-requests/pr-merge-conflict-fixer-workflow-boundary.test.ts index cdab3a70590..e186ba79965 100644 --- a/test/automation/pull-requests/pr-merge-conflict-fixer-workflow-boundary.test.ts +++ b/test/automation/pull-requests/pr-merge-conflict-fixer-workflow-boundary.test.ts @@ -46,7 +46,7 @@ function checkout(job: Record): Record { } function resolverInvocation(command: string): string { - return `node --experimental-strip-types --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" ${command}`; + return `node --no-warnings "$TRUSTED_CHECKOUT/tools/pr-merge-conflict-fixer/resolve.mts" ${command}`; } describe("PR merge conflict fixer workflow boundary", () => { diff --git a/test/automation/pull-requests/pr-review-advisor-local.test.ts b/test/automation/pull-requests/pr-review-advisor-local.test.ts index 11b1ff97b1c..8f9ff9859eb 100644 --- a/test/automation/pull-requests/pr-review-advisor-local.test.ts +++ b/test/automation/pull-requests/pr-review-advisor-local.test.ts @@ -167,7 +167,6 @@ describe("local PR review advisor", () => { execFileSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", path.resolve("tools/pr-review-advisor/export-runtime-env.mts"), ], @@ -272,7 +271,7 @@ describe("local PR review advisor", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", "tools/pr-review-advisor/local-review.mts"], + ["--no-warnings", "tools/pr-review-advisor/local-review.mts"], { cwd: source, encoding: "utf8", @@ -343,7 +342,7 @@ describe("local PR review advisor", () => { git(source, ["fetch", "origin", "main"]); const child = spawn( process.execPath, - ["--experimental-strip-types", "--no-warnings", "tools/pr-review-advisor/local-review.mts"], + ["--no-warnings", "tools/pr-review-advisor/local-review.mts"], { cwd: source, env: { @@ -387,7 +386,6 @@ describe("local PR review advisor", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", path.resolve("tools/pr-review-advisor/local-review.mts"), ], diff --git a/test/automation/pull-requests/pr-review-advisor-openshell.test.ts b/test/automation/pull-requests/pr-review-advisor-openshell.test.ts index baf696a7e28..1f4cbbf1195 100644 --- a/test/automation/pull-requests/pr-review-advisor-openshell.test.ts +++ b/test/automation/pull-requests/pr-review-advisor-openshell.test.ts @@ -765,7 +765,6 @@ describe("PR review advisor OpenShell wrapper", () => { const read = spawnSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", "--input-type=module", "--eval", @@ -1110,10 +1109,9 @@ describe("PR review advisor OpenShell wrapper", () => { expect(createArgs[driverConfigIndex + 1]).not.toContain('"target":"/pr-workdir/'); expect(createArgs).not.toContain("--upload"); expect(createArgs).not.toContain("--no-git-ignore"); - expect(createArgs.slice(-6)).toEqual([ + expect(createArgs.slice(-5)).toEqual([ "--", "/usr/bin/node", - "--experimental-strip-types", "--no-warnings", "/advisor/tools/pr-review-advisor/openshell.mts", "initialize", diff --git a/test/automation/pull-requests/pr-review-advisor-specialists.test.ts b/test/automation/pull-requests/pr-review-advisor-specialists.test.ts index 8ef6bb190e7..d425e8030f8 100644 --- a/test/automation/pull-requests/pr-review-advisor-specialists.test.ts +++ b/test/automation/pull-requests/pr-review-advisor-specialists.test.ts @@ -137,7 +137,7 @@ describe("PR review advisor specialist prompts", () => { const output = execFileSync( process.execPath, - ["--experimental-strip-types", "render-specialist-matrix.mts"], + ["render-specialist-matrix.mts"], { cwd: directory, encoding: "utf8", env: { PATH: process.env.PATH } }, ); const matrix = JSON.parse(output) as Array>; diff --git a/test/automation/pull-requests/pr-workflow-contract.test.ts b/test/automation/pull-requests/pr-workflow-contract.test.ts index c2452451afe..3ad7bb39c01 100644 --- a/test/automation/pull-requests/pr-workflow-contract.test.ts +++ b/test/automation/pull-requests/pr-workflow-contract.test.ts @@ -921,7 +921,7 @@ describe("pull request and main workflow contracts", () => { NODE_AUTH_TOKEN: "${{ github.token }}", }); expect(fetch.run).toContain( - "node --experimental-strip-types scripts/checks/package-openshell-sdk-for-pr.mts", + "node scripts/checks/package-openshell-sdk-for-pr.mts", ); expect(fetch.run).toContain("artifact_path="); expect( diff --git a/test/automation/releases/handoff-summary.test.ts b/test/automation/releases/handoff-summary.test.ts index 07b6c5bd4c6..37079b1c122 100644 --- a/test/automation/releases/handoff-summary.test.ts +++ b/test/automation/releases/handoff-summary.test.ts @@ -29,7 +29,7 @@ function git(cwd: string, ...args: string[]): string { function runCli(cwd: string, ...args: string[]) { return spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", SCRIPT, ...args], + ["--no-warnings", SCRIPT, ...args], { cwd, encoding: "utf8" }, ); } diff --git a/test/automation/releases/npm-audit-receipt.test.ts b/test/automation/releases/npm-audit-receipt.test.ts index 410ab8559bd..4ed30c664a6 100644 --- a/test/automation/releases/npm-audit-receipt.test.ts +++ b/test/automation/releases/npm-audit-receipt.test.ts @@ -184,7 +184,6 @@ describe("reviewed npm audit receipt", () => { : receipt(new Date()); fs.writeFileSync(path.join(root, "receipt.json"), canonicalAuditReceipt(auditReceipt)); const verifierArgs = [ - "--experimental-strip-types", path.join(import.meta.dirname, "../../../scripts/lib/npm-audit-receipt.mts"), "--receipt", path.join(root, "receipt.json"), @@ -239,7 +238,6 @@ describe("reviewed npm audit receipt", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", path.join(import.meta.dirname, "../../../scripts/lib/npm-audit-receipt.mts"), "--receipt", path.join(root, "receipt.json"), diff --git a/test/automation/releases/nvd-reconciliation.test.ts b/test/automation/releases/nvd-reconciliation.test.ts index b0dc5c6efe8..737d02348c1 100644 --- a/test/automation/releases/nvd-reconciliation.test.ts +++ b/test/automation/releases/nvd-reconciliation.test.ts @@ -507,7 +507,7 @@ describe("advisory early-warning CLI --nvd-records", () => { }; function runScanCli(args: readonly string[]): string { - return execFileSync(process.execPath, ["--experimental-strip-types", SCAN_CLI, ...args], { + return execFileSync(process.execPath, [SCAN_CLI, ...args], { encoding: "utf-8", }); } diff --git a/test/automation/releases/release-latest-tag.test.ts b/test/automation/releases/release-latest-tag.test.ts index 28bb9df6dab..90b2932784d 100644 --- a/test/automation/releases/release-latest-tag.test.ts +++ b/test/automation/releases/release-latest-tag.test.ts @@ -213,7 +213,7 @@ function createPlan( const result = runScript( fixture.work, [ - "node", "--experimental-strip-types", "--no-warnings", planScriptPath, + "node", "--no-warnings", planScriptPath, "--version", version, "--output", planPath, ], { NEMOCLAW_RELEASE_ALLOW_NON_CANONICAL: "1" }, @@ -368,14 +368,13 @@ describe("release-latest-tag.sh", () => { const missing = runScript( fixture.work, - ["node", "--experimental-strip-types", "--no-warnings", planScriptPath, "--output", planPath], + ["node", "--no-warnings", planScriptPath, "--output", planPath], { NEMOCLAW_RELEASE_ALLOW_NON_CANONICAL: "1" }, ); const derived = runScript( fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--bump", @@ -389,7 +388,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -403,7 +401,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -439,7 +436,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -469,7 +465,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -509,7 +504,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -582,7 +576,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", @@ -1403,7 +1396,6 @@ describe("release-latest-tag.sh", () => { fixture.work, [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", diff --git a/test/automation/releases/retire-release-label.test.ts b/test/automation/releases/retire-release-label.test.ts index 07560734cb8..9748dc96fed 100644 --- a/test/automation/releases/retire-release-label.test.ts +++ b/test/automation/releases/retire-release-label.test.ts @@ -21,7 +21,7 @@ function runRetireReleaseLabel(fakeGh: string, args = ["v1.2.3"]) { try { return spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", "scripts/retire-release-label.mts", ...args], + ["--no-warnings", "scripts/retire-release-label.mts", ...args], { cwd: process.cwd(), encoding: "utf-8", diff --git a/test/automation/releases/reviewed-npm-audit-entrypoint.test.ts b/test/automation/releases/reviewed-npm-audit-entrypoint.test.ts index e0038a04b3c..07937b70b95 100644 --- a/test/automation/releases/reviewed-npm-audit-entrypoint.test.ts +++ b/test/automation/releases/reviewed-npm-audit-entrypoint.test.ts @@ -18,7 +18,6 @@ describe("reviewed npm audit entry point", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", `process.argv[1] = ${JSON.stringify(path.join(root, "missing-entrypoint"))}; await import(${JSON.stringify(pathToFileURL(path.join(REPO_ROOT, "scripts/audit-reviewed-npm-graph.mts")).href)});`, diff --git a/test/automation/releases/reviewed-npm-audit-handoff.test.ts b/test/automation/releases/reviewed-npm-audit-handoff.test.ts index 8b29d29cba4..7e37b5d1882 100644 --- a/test/automation/releases/reviewed-npm-audit-handoff.test.ts +++ b/test/automation/releases/reviewed-npm-audit-handoff.test.ts @@ -74,7 +74,6 @@ describe("reviewed npm audit handoff", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", "await import(process.argv[1])", @@ -139,7 +138,6 @@ describe("reviewed npm audit handoff", () => { const retainedPackageLock = path.join(root, "temporary-graph.package-lock.json"); const transportRawReport = path.join(root, "temporary-graph.raw.json"); const verifierArgs = [ - "--experimental-strip-types", path.join(REPO_ROOT, "scripts", "lib", "npm-audit-receipt.mts"), "--receipt", receiptFile, diff --git a/test/automation/releases/reviewed-npm-audit-workflow.test.ts b/test/automation/releases/reviewed-npm-audit-workflow.test.ts index ece41db6c46..d2bff0aa7d5 100644 --- a/test/automation/releases/reviewed-npm-audit-workflow.test.ts +++ b/test/automation/releases/reviewed-npm-audit-workflow.test.ts @@ -230,7 +230,6 @@ process.exit(0); const result = spawnSync( process.execPath, [ - "--experimental-strip-types", path.join(trustedRootAlias, "scripts/audit-reviewed-npm-graph.mts"), ], { diff --git a/test/credentials/local-credential-helper-suite.ts b/test/credentials/local-credential-helper-suite.ts index 0080c070a9c..4639dafb229 100644 --- a/test/credentials/local-credential-helper-suite.ts +++ b/test/credentials/local-credential-helper-suite.ts @@ -304,7 +304,6 @@ export function registerLocalCredentialHelperTests(group: LocalCredentialHelperT commandCwd?: string, ): string[] { return [ - "--experimental-strip-types", HELPER_PATH, ...helperCliArguments(fields, command, formPath, executionProfile, commandCwd), ]; diff --git a/test/credentials/rebuild-credential-preflight.test.ts b/test/credentials/rebuild-credential-preflight.test.ts index 20c177b3486..4c01e1e540f 100644 --- a/test/credentials/rebuild-credential-preflight.test.ts +++ b/test/credentials/rebuild-credential-preflight.test.ts @@ -60,7 +60,6 @@ function createFixture(opts: { const gatewayProcess = spawn( process.execPath, [ - "--experimental-strip-types", path.join(REPO_ROOT, "test", "helpers", "ephemeral-gateway-listener.ts"), gatewayReadyMarker, ], diff --git a/test/e2e-runtime/candidate-compat.test.ts b/test/e2e-runtime/candidate-compat.test.ts index bb16b25eaa6..2a256bfee6f 100644 --- a/test/e2e-runtime/candidate-compat.test.ts +++ b/test/e2e-runtime/candidate-compat.test.ts @@ -472,7 +472,6 @@ describe("OpenShell candidate compatibility contract", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", resolve("tools/candidate-compat.mts"), "finalize", "--receipt", diff --git a/test/e2e/e2e-cloud-experimental/check-docs.sh b/test/e2e/e2e-cloud-experimental/check-docs.sh index 4de40642e1b..0e65a8ac697 100755 --- a/test/e2e/e2e-cloud-experimental/check-docs.sh +++ b/test/e2e/e2e-cloud-experimental/check-docs.sh @@ -491,7 +491,7 @@ run_install_check() { local _canonical if [[ "$PROVIDERS_TS" == */provider-selection-keys.ts ]]; then _canonical="$( - "$NODE" --experimental-strip-types --no-warnings --input-type=module -e ' + "$NODE" --no-warnings --input-type=module -e ' import { pathToFileURL } from "node:url"; const source = await import(pathToFileURL(process.argv[1]).href); const prefix = "Valid values: "; diff --git a/test/e2e/fixtures/fake-openai-compatible.ts b/test/e2e/fixtures/fake-openai-compatible.ts index 5319e6e2db4..1efc8c948d4 100644 --- a/test/e2e/fixtures/fake-openai-compatible.ts +++ b/test/e2e/fixtures/fake-openai-compatible.ts @@ -172,7 +172,7 @@ export async function startFakeOpenAiCompatibleServer( const host = options.host ?? "127.0.0.1"; let child: ChildProcess; try { - child = spawnObservedChild(process.execPath, ["--experimental-strip-types", SERVER_SCRIPT], { + child = spawnObservedChild(process.execPath, [SERVER_SCRIPT], { activityLabel: "command: fake-openai-compatible-server", progress: options.progress, spawn: { diff --git a/test/e2e/lib/fake-discord-message-api.mts b/test/e2e/lib/fake-discord-message-api.mts index b2b195702be..543cd7f86ee 100755 --- a/test/e2e/lib/fake-discord-message-api.mts +++ b/test/e2e/lib/fake-discord-message-api.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/test/e2e/lib/fake-openai-compatible-api.mts b/test/e2e/lib/fake-openai-compatible-api.mts index fade72cd5ce..d2e09d444bd 100755 --- a/test/e2e/lib/fake-openai-compatible-api.mts +++ b/test/e2e/lib/fake-openai-compatible-api.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/test/e2e/lib/fake-wechat-api.mts b/test/e2e/lib/fake-wechat-api.mts index 45d72ffe761..d968521cd1e 100755 --- a/test/e2e/lib/fake-wechat-api.mts +++ b/test/e2e/lib/fake-wechat-api.mts @@ -1,4 +1,4 @@ -#!/usr/bin/env -S node --experimental-strip-types +#!/usr/bin/env node // SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. // SPDX-License-Identifier: Apache-2.0 diff --git a/test/e2e/lib/openai-compatible-api-proof.sh b/test/e2e/lib/openai-compatible-api-proof.sh index d1c813fbce7..f10b744a3eb 100755 --- a/test/e2e/lib/openai-compatible-api-proof.sh +++ b/test/e2e/lib/openai-compatible-api-proof.sh @@ -26,7 +26,7 @@ start_fake_openai_compatible_api() { NEMOCLAW_FAKE_OPENAI_REQUIRE_AUTH="${FAKE_OPENAI_REQUIRE_AUTH:-0}" \ NEMOCLAW_FAKE_OPENAI_CHAT_CONTENT="${FAKE_OPENAI_CHAT_CONTENT:-ok}" \ NEMOCLAW_FAKE_OPENAI_RESPONSE_TEXT="${FAKE_OPENAI_RESPONSE_TEXT:-${FAKE_OPENAI_CHAT_CONTENT:-ok}}" \ - node --experimental-strip-types "$server_script" & + node "$server_script" & FAKE_OPENAI_PID="$!" for _ in $(seq 1 "${FAKE_OPENAI_READY_ATTEMPTS:-30}"); do diff --git a/test/e2e/live/hermes-discord.test.ts b/test/e2e/live/hermes-discord.test.ts index bdf29fc6b69..4aebb8f688d 100644 --- a/test/e2e/live/hermes-discord.test.ts +++ b/test/e2e/live/hermes-discord.test.ts @@ -686,7 +686,6 @@ PY`, const fakeRest = await startFakeDockerApi(host, cleanup.trackDisposable.bind(cleanup), { kind: "discord-message", imageScript: "fake-discord-message-api.mts", - nodeArgs: ["--experimental-strip-types"], containerPrefix: "nemoclaw-fake-discord-rest-hermes", portEnv: "FAKE_DISCORD_MESSAGE_API_PORT", captureFileEnv: "FAKE_DISCORD_MESSAGE_API_CAPTURE_FILE", diff --git a/test/e2e/live/messaging-providers.test.ts b/test/e2e/live/messaging-providers.test.ts index 59e2fccb15f..6fcc6fe6e25 100644 --- a/test/e2e/live/messaging-providers.test.ts +++ b/test/e2e/live/messaging-providers.test.ts @@ -1092,7 +1092,6 @@ req.setTimeout(30000, () => { req.destroy(); console.log("TIMEOUT"); }); const fakeWechat = await startFakeDockerApi(host, cleanup.add.bind(cleanup), { kind: "wechat", imageScript: "fake-wechat-api.mts", - nodeArgs: ["--experimental-strip-types"], containerPrefix: "nemoclaw-fake-wechat", portEnv: "FAKE_WECHAT_API_PORT", captureFileEnv: "FAKE_WECHAT_API_CAPTURE_FILE", diff --git a/test/e2e/support/base-image-publication.test.ts b/test/e2e/support/base-image-publication.test.ts index 121d68155b6..f1d7093862e 100644 --- a/test/e2e/support/base-image-publication.test.ts +++ b/test/e2e/support/base-image-publication.test.ts @@ -1200,7 +1200,6 @@ describe("base-image publication evidence", () => { execFileSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", "--eval", `import(${JSON.stringify(modulePath)})`, diff --git a/test/e2e/support/e2e-scorecard.test.ts b/test/e2e/support/e2e-scorecard.test.ts index 6d3e5ea4978..d20377d894c 100644 --- a/test/e2e/support/e2e-scorecard.test.ts +++ b/test/e2e/support/e2e-scorecard.test.ts @@ -199,7 +199,7 @@ describe("E2E scorecard", () => { const artifactZip = require(path.join(process.env.GITHUB_WORKSPACE, 'scripts/lib/read-artifact-zip.mts')); if (Object.keys(artifactZip).length === 0) process.exit(2); `; - const result = spawnSync(process.execPath, ["--experimental-strip-types", "-e", script], { + const result = spawnSync(process.execPath, ["-e", script], { cwd: process.cwd(), encoding: "utf8", env: { ...process.env, GITHUB_WORKSPACE: process.cwd() }, diff --git a/test/e2e/support/hermes-langfuse-credential-patch.test.ts b/test/e2e/support/hermes-langfuse-credential-patch.test.ts index 00609cf1427..d717c2acbe4 100644 --- a/test/e2e/support/hermes-langfuse-credential-patch.test.ts +++ b/test/e2e/support/hermes-langfuse-credential-patch.test.ts @@ -122,7 +122,7 @@ describe("Hermes Langfuse OpenShell credential compatibility", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", patcherPath, fixturePath], + [patcherPath, fixturePath], { encoding: "utf8" }, ); diff --git a/test/e2e/support/jetson-managed-revision-boundary.test.ts b/test/e2e/support/jetson-managed-revision-boundary.test.ts index 3c4c7b77ac6..4d8db04a5ca 100644 --- a/test/e2e/support/jetson-managed-revision-boundary.test.ts +++ b/test/e2e/support/jetson-managed-revision-boundary.test.ts @@ -59,7 +59,7 @@ function syntheticJetsonWorkflow(selector = REQUIRED_SELECTOR): unknown { JETSON_DISPATCH_URL: "${{ vars.JETSON_DISPATCH_URL }}", }, name: "Dispatch exact commit to Jetson through operator backend", - run: "node --experimental-strip-types --no-warnings tools/e2e/jetson-dispatch-client.mts", + run: "node --no-warnings tools/e2e/jetson-dispatch-client.mts", }, { if: "always()", diff --git a/test/e2e/support/messaging-providers-runtime-proofs.test.ts b/test/e2e/support/messaging-providers-runtime-proofs.test.ts index e301fad881b..a0599b0c128 100644 --- a/test/e2e/support/messaging-providers-runtime-proofs.test.ts +++ b/test/e2e/support/messaging-providers-runtime-proofs.test.ts @@ -1422,7 +1422,7 @@ describe("messaging provider installed-runtime proofs", () => { const portFile = path.join(dir, "port"); const captureFile = path.join(dir, "capture.jsonl"); const token = "test-secret-wechat-ilink-token"; - const child = spawn(process.execPath, ["--experimental-strip-types", FAKE_WECHAT_API], { + const child = spawn(process.execPath, [FAKE_WECHAT_API], { env: { ...process.env, FAKE_WECHAT_API_HOST: "127.0.0.1", diff --git a/test/e2e/support/native-runtime-qualification-collector-workflow.test.ts b/test/e2e/support/native-runtime-qualification-collector-workflow.test.ts index 49d74188119..7e6e93c1a60 100644 --- a/test/e2e/support/native-runtime-qualification-collector-workflow.test.ts +++ b/test/e2e/support/native-runtime-qualification-collector-workflow.test.ts @@ -118,7 +118,7 @@ describe("native runtime qualification collector workflow", () => { (collect as WorkflowStep & { readonly "working-directory"?: string })["working-directory"], ).toBe("trusted"); expect(collect.run).toContain( - "node --experimental-strip-types --no-warnings tools/e2e/native-runtime-qualification-collector.mts", + "node --no-warnings tools/e2e/native-runtime-qualification-collector.mts", ); expect(tokenSteps.map((step) => step.name)).toEqual([ "Authenticate and consume protected qualification evidence", diff --git a/test/e2e/support/openshell-gateway-auth-contract-workflow-boundary.test.ts b/test/e2e/support/openshell-gateway-auth-contract-workflow-boundary.test.ts index 095d68b4472..f9885efe489 100644 --- a/test/e2e/support/openshell-gateway-auth-contract-workflow-boundary.test.ts +++ b/test/e2e/support/openshell-gateway-auth-contract-workflow-boundary.test.ts @@ -82,7 +82,7 @@ describe("OpenShell gateway auth contract workflow boundary", () => { "openshell-gateway-auth-contract step 'Pre-pull pinned gateway auth probe image' must run: docker pull \"$DOCKER_GRPC_PROBE_IMAGE\"", "openshell-gateway-auth-contract live test must not receive workflow credentials", "openshell-gateway-auth-contract final artifact safety scan must run unconditionally with a stable id", - "openshell-gateway-auth-contract step 'Validate final OpenShell gateway auth contract artifacts' must run exactly: node --experimental-strip-types --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts \"$E2E_ARTIFACT_DIR\"", + "openshell-gateway-auth-contract step 'Validate final OpenShell gateway auth contract artifacts' must run exactly: node --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts \"$E2E_ARTIFACT_DIR\"", "openshell-gateway-auth-contract must use the reviewed artifact uploader", "openshell-gateway-auth-contract must upload artifacts only after this run attempt passes safety scan", "openshell-gateway-auth-contract must upload only the immutable approved artifact payload", @@ -100,7 +100,7 @@ describe("OpenShell gateway auth contract workflow boundary", () => { artifactSafety.run = `${artifactSafety.run} || true`; expect(validateOpenShellGatewayAuthContractWorkflow(workflow)).toContain( - "openshell-gateway-auth-contract step 'Validate final OpenShell gateway auth contract artifacts' must run exactly: node --experimental-strip-types --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts \"$E2E_ARTIFACT_DIR\"", + "openshell-gateway-auth-contract step 'Validate final OpenShell gateway auth contract artifacts' must run exactly: node --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts \"$E2E_ARTIFACT_DIR\"", ); }); }); diff --git a/test/e2e/support/openshell-gateway-upgrade-old-installer.test.ts b/test/e2e/support/openshell-gateway-upgrade-old-installer.test.ts index bfd8543d634..b06918e67ba 100644 --- a/test/e2e/support/openshell-gateway-upgrade-old-installer.test.ts +++ b/test/e2e/support/openshell-gateway-upgrade-old-installer.test.ts @@ -169,7 +169,6 @@ writeFileSync(outputPath, staged.buildCtx); process.execPath, [ "--no-warnings", - "--experimental-strip-types", "--input-type=module", "--eval", runner, diff --git a/test/e2e/support/podman-cpu-proof-workflow.test.ts b/test/e2e/support/podman-cpu-proof-workflow.test.ts index 821bc7ea438..b22038b1109 100644 --- a/test/e2e/support/podman-cpu-proof-workflow.test.ts +++ b/test/e2e/support/podman-cpu-proof-workflow.test.ts @@ -760,7 +760,6 @@ describe("native Podman CPU proof workflow", () => { const imported = spawnSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", "--input-type=module", "-e", @@ -775,14 +774,14 @@ describe("native Podman CPU proof workflow", () => { ); const rejected = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", scriptPath, "unknown"], + ["--no-warnings", scriptPath, "unknown"], { cwd: path.resolve("."), encoding: "utf8", env }, ); expect(rejected.status).toBe(1); expect(rejected.stderr).toContain("Expected exactly one mode"); const cleaned = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", scriptPath, "cleanup"], + ["--no-warnings", scriptPath, "cleanup"], { cwd: path.resolve("."), encoding: "utf8", env }, ); expect(cleaned.status).toBe(0); @@ -793,7 +792,7 @@ describe("native Podman CPU proof workflow", () => { ); const signaled = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", scriptPath, "cleanup"], + ["--no-warnings", scriptPath, "cleanup"], { cwd: path.resolve("."), encoding: "utf8", env }, ); expect(signaled.status).toBe(1); diff --git a/test/e2e/support/pr-self-hosted-llama-selector.test.ts b/test/e2e/support/pr-self-hosted-llama-selector.test.ts index c86b2d3c803..235449efc95 100644 --- a/test/e2e/support/pr-self-hosted-llama-selector.test.ts +++ b/test/e2e/support/pr-self-hosted-llama-selector.test.ts @@ -217,7 +217,7 @@ describe("generic NVIDIA GPU PR selection", () => { expect(publication?.run).toContain("export GITHUB_REF=refs/heads/main"); expect(publication?.run).toContain('export GITHUB_SHA="$EXPECTED_SHA"'); expect(publication?.run).toContain( - "node --experimental-strip-types --no-warnings tools/e2e/base-image-publication.mts --wait-seconds 3000 --poll-seconds 30", + "node --no-warnings tools/e2e/base-image-publication.mts --wait-seconds 3000 --poll-seconds 30", ); expect(value.jobs["llama-cpp-generic-gpu"]?.env?.E2E_MANAGED_IMAGE_REVISION).toBe( diff --git a/test/e2e/support/prepare-e2e-workflow-boundary.test.ts b/test/e2e/support/prepare-e2e-workflow-boundary.test.ts index e72ec479cd5..c9224bbb66e 100644 --- a/test/e2e/support/prepare-e2e-workflow-boundary.test.ts +++ b/test/e2e/support/prepare-e2e-workflow-boundary.test.ts @@ -59,10 +59,7 @@ describe("prepare-e2e workflow boundary", () => { }); const result = spawnSync( process.execPath, - [ - "--experimental-strip-types", - path.join(root, "scripts/checks/prepare-ci-npm-install.mts"), - ], + [path.join(root, "scripts/checks/prepare-ci-npm-install.mts")], { encoding: "utf8", cwd: root, diff --git a/test/e2e/support/release-qualification.test.ts b/test/e2e/support/release-qualification.test.ts index 8eef3ad8ffa..711cfd0c884 100644 --- a/test/e2e/support/release-qualification.test.ts +++ b/test/e2e/support/release-qualification.test.ts @@ -71,7 +71,6 @@ describe("release qualification", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", path.join(process.cwd(), "tools/e2e/release-qualification.mts"), ], diff --git a/test/e2e/support/runner-pressure.test.ts b/test/e2e/support/runner-pressure.test.ts index 7d47ee2decc..466e9afee39 100644 --- a/test/e2e/support/runner-pressure.test.ts +++ b/test/e2e/support/runner-pressure.test.ts @@ -67,7 +67,7 @@ const LINK_CREATORS = { } as const; function runHelper(args: string[], env: Record) { - return spawnSync(process.execPath, ["--experimental-strip-types", HELPER, ...args], { + return spawnSync(process.execPath, [HELPER, ...args], { encoding: "utf-8", env: { ...process.env, ...env }, }); diff --git a/test/e2e/support/same-commit-reliability.test.ts b/test/e2e/support/same-commit-reliability.test.ts index ea4e85b03e4..84ee9b59fd6 100644 --- a/test/e2e/support/same-commit-reliability.test.ts +++ b/test/e2e/support/same-commit-reliability.test.ts @@ -86,7 +86,7 @@ describe("same-commit reliability reporter entrypoint", () => { it("loads with the raw Node strip-types runtime used by CI", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", REPORTER_PATH], + ["--no-warnings", REPORTER_PATH], { encoding: "utf8", env: { ...process.env, GITHUB_TOKEN: "", SOURCE_RUN_ID: "" }, diff --git a/test/generation/generate-hermes-config.test.ts b/test/generation/generate-hermes-config.test.ts index 107c2115c2e..bf75b420490 100644 --- a/test/generation/generate-hermes-config.test.ts +++ b/test/generation/generate-hermes-config.test.ts @@ -182,7 +182,7 @@ function runConfigScriptRaw( const env = buildHermesTestEnv(envOverrides); return spawnSync( process.execPath, - ["--experimental-strip-types", opts.scriptPath || SCRIPT_PATH], + [opts.scriptPath || SCRIPT_PATH], { encoding: "utf-8", cwd: opts.cwd, diff --git a/test/generation/generate-managed-startup-profile-fixture.test.ts b/test/generation/generate-managed-startup-profile-fixture.test.ts index bce3567929c..53e81ac4724 100644 --- a/test/generation/generate-managed-startup-profile-fixture.test.ts +++ b/test/generation/generate-managed-startup-profile-fixture.test.ts @@ -32,7 +32,7 @@ const CORPORATE_CA_SHA256 = createHash("sha256") function runFixture(args: readonly string[]) { return spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", SCRIPT_PATH, ...args], + ["--no-warnings", SCRIPT_PATH, ...args], { encoding: "utf8", timeout: 10_000, diff --git a/test/generation/generate-openclaw-config-agents-manifest.test.ts b/test/generation/generate-openclaw-config-agents-manifest.test.ts index 74387798832..da1691f0ba4 100644 --- a/test/generation/generate-openclaw-config-agents-manifest.test.ts +++ b/test/generation/generate-openclaw-config-agents-manifest.test.ts @@ -62,7 +62,6 @@ function runMessagingPostInstall(env: Record): void { const result = spawnSync( "node", [ - "--experimental-strip-types", APPLIER_PATH, "--agent", "openclaw", diff --git a/test/generation/generate-openclaw-config.test.ts b/test/generation/generate-openclaw-config.test.ts index 691b2accad5..0dc969358df 100644 --- a/test/generation/generate-openclaw-config.test.ts +++ b/test/generation/generate-openclaw-config.test.ts @@ -26,7 +26,7 @@ const SCRIPT_PATH = path.join( "scripts", "generate-openclaw-config.mts", ); -const SCRIPT_ARGS = ["--experimental-strip-types", SCRIPT_PATH]; +const SCRIPT_ARGS = [SCRIPT_PATH]; /** Minimal env vars required for a valid config generation run. */ const BASE_ENV = baseOpenClawGenerationEnv(); @@ -218,7 +218,7 @@ describe("generate-openclaw-config.mts: config generation", () => { expect(config.agents).toBeDefined(); }); - it("runs as a node --experimental-strip-types executable", () => { + it("runs as a node executable", () => { const config = runConfigSubprocess(); expect(config.gateway).toBeDefined(); expect(config.models).toBeDefined(); diff --git a/test/helpers/historical-release-fixture.ts b/test/helpers/historical-release-fixture.ts index 57f30acea98..d719211b09c 100644 --- a/test/helpers/historical-release-fixture.ts +++ b/test/helpers/historical-release-fixture.ts @@ -97,7 +97,6 @@ export function pushTag(fixture: HistoricalReleaseFixture, tag: string, target: export function planArguments(candidate: string, exception?: string, output?: string): string[] { const args = [ "node", - "--experimental-strip-types", "--no-warnings", planScriptPath, "--version", diff --git a/test/helpers/openclaw-device-self-approval-patch-harness.ts b/test/helpers/openclaw-device-self-approval-patch-harness.ts index a9edd7680b9..cca277e0ad3 100644 --- a/test/helpers/openclaw-device-self-approval-patch-harness.ts +++ b/test/helpers/openclaw-device-self-approval-patch-harness.ts @@ -786,7 +786,7 @@ export function writeFixtureDist(dist: string): void { export function runPatch(dist: string, audit = false) { return spawnSync( process.execPath, - ["--experimental-strip-types", PATCH_SCRIPT, ...(audit ? ["--audit"] : []), dist], + [PATCH_SCRIPT, ...(audit ? ["--audit"] : []), dist], { encoding: "utf8", timeout: 10_000, diff --git a/test/helpers/openclaw-real-device-self-approval-proof.ts b/test/helpers/openclaw-real-device-self-approval-proof.ts index ffd060949b2..1bfe7956f96 100644 --- a/test/helpers/openclaw-real-device-self-approval-proof.ts +++ b/test/helpers/openclaw-real-device-self-approval-proof.ts @@ -2182,7 +2182,7 @@ fs.statSync = function nemoclawProofStatSync(candidate, ...args) { export async function runRealOpenClawDeviceSelfApprovalProof(options: ProofOptions): Promise { const patch = spawnSync( options.nodeExecutable, - ["--experimental-strip-types", options.patchScript, options.dist], + [options.patchScript, options.dist], { encoding: "utf8", timeout: options.timeoutMs, @@ -2197,7 +2197,7 @@ export async function runRealOpenClawDeviceSelfApprovalProof(options: ProofOptio const audit = spawnSync( options.nodeExecutable, - ["--experimental-strip-types", options.patchScript, "--audit", options.dist], + [options.patchScript, "--audit", options.dist], { encoding: "utf8", timeout: options.timeoutMs, diff --git a/test/helpers/openclaw-real-mcp-start-retry-proof.ts b/test/helpers/openclaw-real-mcp-start-retry-proof.ts index c1d3c0193d2..79a52fd5824 100644 --- a/test/helpers/openclaw-real-mcp-start-retry-proof.ts +++ b/test/helpers/openclaw-real-mcp-start-retry-proof.ts @@ -48,14 +48,14 @@ function requireEqual(actual: string, expected: string, label: string): void { export function runRealOpenClawMcpStartRetryProof(options: ProofOptions): void { const applied = spawnSync( options.nodeExecutable, - ["--experimental-strip-types", options.patchScript, options.dist], + [options.patchScript, options.dist], { encoding: "utf8", timeout: options.timeoutMs }, ); requireSuccess(applied, "apply MCP startup recovery patch"); const audit = spawnSync( options.nodeExecutable, - ["--experimental-strip-types", options.patchScript, "--audit", options.dist], + [options.patchScript, "--audit", options.dist], { encoding: "utf8", timeout: options.timeoutMs }, ); requireSuccess(audit, "audit MCP startup recovery patch"); diff --git a/test/inference/llama/llama-cpp-image-workflow.test.ts b/test/inference/llama/llama-cpp-image-workflow.test.ts index 37125000cfe..1f4658f4887 100644 --- a/test/inference/llama/llama-cpp-image-workflow.test.ts +++ b/test/inference/llama/llama-cpp-image-workflow.test.ts @@ -274,7 +274,7 @@ describe("llama.cpp image PR workflow", () => { ), ).toBe(true); expect(namedStep(config, "Compile image manifest").run).toBe( - "node --experimental-strip-types --no-warnings scripts/checks/export-llama-cpp-image-config.mts", + "node --no-warnings scripts/checks/export-llama-cpp-image-config.mts", ); expect(build.needs).toBe("config"); expect(build["runs-on"]).toBe("${{ matrix.runner }}"); diff --git a/test/inference/llama/llama-cpp-image.test.ts b/test/inference/llama/llama-cpp-image.test.ts index d87b0424dcd..cfa5195d2b0 100644 --- a/test/inference/llama/llama-cpp-image.test.ts +++ b/test/inference/llama/llama-cpp-image.test.ts @@ -302,7 +302,7 @@ describe("declarative llama.cpp server image", () => { it("compiles the fail-closed workflow inputs from YAML (#8231)", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", exporterPath], + ["--no-warnings", exporterPath], { cwd: repoRoot, encoding: "utf8", diff --git a/test/inference/managed/issue-5667-hosted-inference-model-namespace.test.ts b/test/inference/managed/issue-5667-hosted-inference-model-namespace.test.ts index d729a1f91f9..2ed6b47fc4e 100644 --- a/test/inference/managed/issue-5667-hosted-inference-model-namespace.test.ts +++ b/test/inference/managed/issue-5667-hosted-inference-model-namespace.test.ts @@ -300,7 +300,6 @@ const { setupNim } = require(${onboardPath}); const configResult = spawnSync( process.execPath, [ - "--experimental-strip-types", path.join(REPO_ROOT, "agents", "langchain-deepagents-code", "generate-config.ts"), ], { diff --git a/test/install/installer-homebrew-formula-reuse-trust.test.ts b/test/install/installer-homebrew-formula-reuse-trust.test.ts index 6c5aedf4fdf..ec8d63e6c6e 100644 --- a/test/install/installer-homebrew-formula-reuse-trust.test.ts +++ b/test/install/installer-homebrew-formula-reuse-trust.test.ts @@ -72,7 +72,6 @@ function runTrustCheck(source: string) { return spawnSync( process.execPath, [ - "--experimental-strip-types", path.join(REPO_ROOT, "scripts/checks/extract-installer-pins.mts"), "--blueprint", path.join(REPO_ROOT, "nemoclaw-blueprint/blueprint.yaml"), diff --git a/test/install/installer-sandbox-build-trust.test.ts b/test/install/installer-sandbox-build-trust.test.ts index daa21a796a5..e8b1f28c6ef 100644 --- a/test/install/installer-sandbox-build-trust.test.ts +++ b/test/install/installer-sandbox-build-trust.test.ts @@ -130,7 +130,6 @@ function runParser(mutate: (source: string) => string = (source) => source) { return spawnSync( "node", [ - "--experimental-strip-types", "--no-warnings", PARSER, "--blueprint", diff --git a/test/install/installer-supervisor-manifest-trust.test.ts b/test/install/installer-supervisor-manifest-trust.test.ts index a46d661a4bc..78719a12de1 100644 --- a/test/install/installer-supervisor-manifest-trust.test.ts +++ b/test/install/installer-supervisor-manifest-trust.test.ts @@ -202,7 +202,6 @@ function runParser(options: RunOptions = {}) { return spawnSync( "node", [ - "--experimental-strip-types", "--no-warnings", PARSER, "--blueprint", diff --git a/test/install/update-hermes-agent-script.test.ts b/test/install/update-hermes-agent-script.test.ts index 6855962d276..6e349fc8853 100644 --- a/test/install/update-hermes-agent-script.test.ts +++ b/test/install/update-hermes-agent-script.test.ts @@ -35,7 +35,7 @@ const CURRENT_INSTALLED_DOCKERFILE = [ "COPY agents/hermes/mcp-config-transaction.py /usr/local/lib/nemoclaw/hermes-mcp-config-transaction.py", "COPY src/lib/actions/sandbox/openshell-child-visible-credentials.v0.0.106.json /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.106.json", "RUN HERMES_HOME=/sandbox/.hermes /usr/local/bin/hermes doctor --fix \\", - " && node --experimental-strip-types /opt/nemoclaw-hermes-config/generate-config.ts", + " && node /opt/nemoclaw-hermes-config/generate-config.ts", "RUN mkdir -p /sandbox/.hermes/profiles/dashboard-home", "", ].join("\n"); diff --git a/test/installer-integration/install-station-pair-preparation.test.ts b/test/installer-integration/install-station-pair-preparation.test.ts index ec8eefb1b7b..a215bd7f056 100644 --- a/test/installer-integration/install-station-pair-preparation.test.ts +++ b/test/installer-integration/install-station-pair-preparation.test.ts @@ -978,7 +978,6 @@ fi process.execPath, [ "--no-warnings", - "--experimental-strip-types", COORDINATOR, "--helper", helper, @@ -1129,7 +1128,6 @@ exit 96 process.execPath, [ "--no-warnings", - "--experimental-strip-types", COORDINATOR, "--helper", helper, diff --git a/test/networking/dashboard-remote-bind-lifecycle.test.ts b/test/networking/dashboard-remote-bind-lifecycle.test.ts index 6423135b53a..154cb5a9e3a 100644 --- a/test/networking/dashboard-remote-bind-lifecycle.test.ts +++ b/test/networking/dashboard-remote-bind-lifecycle.test.ts @@ -33,7 +33,7 @@ function remoteBindDockerfile(...postGeneratorInstructions: string[]): string { "ARG CHAT_UI_URL=", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", ...postGeneratorInstructions, ].join("\n"); } @@ -81,7 +81,7 @@ describe("remote dashboard bind production lifecycle", () => { const dockerfile = path.join(directory, "Dockerfile"); const stockDockerfile = fs.readFileSync(path.join(process.cwd(), "Dockerfile"), "utf8"); const generator = - "RUN NEMOCLAW_OPENCLAW_MANAGED_PROXY=0 node --experimental-strip-types /scripts/generate-openclaw-config.mts"; + "RUN NEMOCLAW_OPENCLAW_MANAGED_PROXY=0 node /scripts/generate-openclaw-config.mts"; const proxyPatch = 'RUN python3 -c "\\\n'; const configHash = "RUN sha256sum /sandbox/.openclaw/openclaw.json > /sandbox/.openclaw/.config-hash"; @@ -176,7 +176,7 @@ describe("remote dashboard bind production lifecycle", () => { "ARG NEMOCLAW_DASHBOARD_BIND=", "ARG NEMOCLAW_DISABLE_DEVICE_AUTH=0", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", ].join("\n"), ); @@ -288,7 +288,7 @@ describe("remote dashboard bind production lifecycle", () => { "FROM scratch AS decoy", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", "FROM scratch", "ARG NEMOCLAW_MODEL=", "ARG CHAT_UI_URL=", @@ -318,7 +318,7 @@ describe("remote dashboard bind production lifecycle", () => { "ARG CHAT_UI_URL=", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", "RUN printf '{}' > /sandbox/.openclaw/openclaw.json", ].join("\n"), ); @@ -337,8 +337,8 @@ describe("remote dashboard bind production lifecycle", () => { [ "generator", remoteBindDockerfile().replace( - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts && printf '{}' > /sandbox/.openclaw/openclaw.json", + "RUN node /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts && printf '{}' > /sandbox/.openclaw/openclaw.json", ), ], [ @@ -436,7 +436,7 @@ describe("remote dashboard bind production lifecycle", () => { "ARG CHAT_UI_URL=", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", "RUN chmod 660 /sandbox/.openclaw/openclaw.json", "RUN sha256sum /sandbox/.openclaw/openclaw.json > /sandbox/.openclaw/.config-hash", ].join("\n"), @@ -506,8 +506,8 @@ describe("remote dashboard bind production lifecycle", () => { "ARG CHAT_UI_URL=", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", + "RUN node /scripts/generate-openclaw-config.mts", ].join("\n"), ); @@ -533,8 +533,8 @@ describe("remote dashboard bind production lifecycle", () => { "ARG CHAT_UI_URL=", "ARG NEMOCLAW_DASHBOARD_BIND=", "ENV NEMOCLAW_DASHBOARD_BIND=${NEMOCLAW_DASHBOARD_BIND}", - "RUN node --experimental-strip-types /scripts/generate-openclaw-config.mts", - 'RUN validation_home="$validation_root/progressive"; HOME="$validation_home" node --experimental-strip-types /scripts/generate-openclaw-config.mts', + "RUN node /scripts/generate-openclaw-config.mts", + 'RUN validation_home="$validation_root/progressive"; HOME="$validation_home" node /scripts/generate-openclaw-config.mts', ].join("\n"), ); diff --git a/test/package-contract/openshell-policy-boundary.test.ts b/test/package-contract/openshell-policy-boundary.test.ts index 97df6563199..27d1568e654 100644 --- a/test/package-contract/openshell-policy-boundary.test.ts +++ b/test/package-contract/openshell-policy-boundary.test.ts @@ -274,7 +274,6 @@ describe("OpenShell policy boundary package contract", () => { execFileSync( process.execPath, [ - "--experimental-strip-types", "--no-warnings", "--eval", `const contract = require(${JSON.stringify(controlContractPath)}); process.stdout.write(JSON.stringify([contract.isValidName("packaged-hermes"), contract.isValidName("../packaged-hermes")]));`, diff --git a/test/platform/images/bundled-npm-brace-expansion-dockerfile-contract.test.ts b/test/platform/images/bundled-npm-brace-expansion-dockerfile-contract.test.ts index 229fa255535..cef18e5cd36 100644 --- a/test/platform/images/bundled-npm-brace-expansion-dockerfile-contract.test.ts +++ b/test/platform/images/bundled-npm-brace-expansion-dockerfile-contract.test.ts @@ -28,7 +28,7 @@ const finalDockerfiles = [ const copyInstruction = "COPY scripts/patch-bundled-npm-brace-expansion.mts /scripts/patch-bundled-npm-brace-expansion.mts"; const patchInstruction = - "node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts"; + "node /scripts/patch-bundled-npm-brace-expansion.mts"; const npmRootArguments = ["--npm-root", "/usr/local/lib/node_modules/npm"] as const; const hermesTarCacheSeedArguments = [ ...npmRootArguments, @@ -57,7 +57,7 @@ describe("bundled npm brace-expansion image remediation contract", () => { const copy = source.indexOf(copyInstruction); const upgrade = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/upgrade-bundled-npm.mts", + "node /scripts/upgrade-bundled-npm.mts", npmRootArguments, ).commandStart; const patch = requireSingleReviewedDockerfileRunCommand( @@ -78,7 +78,7 @@ describe("bundled npm brace-expansion image remediation contract", () => { const copy = source.indexOf(copyInstruction); const tarPatch = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", + "node /scripts/patch-bundled-npm-tar.mts", tarPatchArgumentsByDockerfile[file], ).commandStart; const bracePatch = requireSingleReviewedDockerfileRunCommand( diff --git a/test/platform/images/bundled-npm-ip-address-dockerfile-contract.test.ts b/test/platform/images/bundled-npm-ip-address-dockerfile-contract.test.ts index f7795c3074d..a848f833fed 100644 --- a/test/platform/images/bundled-npm-ip-address-dockerfile-contract.test.ts +++ b/test/platform/images/bundled-npm-ip-address-dockerfile-contract.test.ts @@ -28,7 +28,7 @@ const finalDockerfiles = [ const copyInstruction = "COPY scripts/lib/patch-bundled-npm-ip-address.mts /scripts/lib/patch-bundled-npm-ip-address.mts"; const patchCommand = - "node --experimental-strip-types /scripts/lib/patch-bundled-npm-ip-address.mts"; + "node /scripts/lib/patch-bundled-npm-ip-address.mts"; const npmRootArguments = ["--npm-root", "/usr/local/lib/node_modules/npm"] as const; const hermesTarCacheSeedArguments = [ ...npmRootArguments, @@ -59,7 +59,7 @@ describe("bundled npm ip-address image remediation contract", () => { const copy = source.indexOf(copyInstruction); const upgrade = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/upgrade-bundled-npm.mts", + "node /scripts/upgrade-bundled-npm.mts", npmRootArguments, ).commandStart; const patch = requireSingleReviewedDockerfileRunCommand(source, patchCommand, npmRootArguments); @@ -74,12 +74,12 @@ describe("bundled npm ip-address image remediation contract", () => { const copy = source.indexOf(copyInstruction); const tarPatch = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts", + "node /scripts/patch-bundled-npm-tar.mts", tarPatchArgumentsByDockerfile[file], ).commandStart; const bracePatch = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/patch-bundled-npm-brace-expansion.mts", + "node /scripts/patch-bundled-npm-brace-expansion.mts", npmRootArguments, ).commandStart; const ipAddressPatch = requireSingleReviewedDockerfileRunCommand( diff --git a/test/platform/images/dockerfile-run-commands.test.ts b/test/platform/images/dockerfile-run-commands.test.ts index fb34a178c72..f5e151feb9c 100644 --- a/test/platform/images/dockerfile-run-commands.test.ts +++ b/test/platform/images/dockerfile-run-commands.test.ts @@ -7,11 +7,11 @@ import { requireSingleReviewedDockerfileRunCommand, } from "../../helpers/dockerfile-run-commands"; -const command = "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts"; +const command = "node /scripts/patch-bundled-npm-tar.mts"; const corporateCaPath = "/usr/local/share/nemoclaw/corporate-ca.pem"; const requiredArguments = ["--npm-root", "/usr/local/lib/node_modules/npm"] as const; const invocation = [command, ...requiredArguments].join(" "); -const splicedCommand = command.replace("strip-types", "strip-\\\ntypes"); +const splicedCommand = command.replace("bundled-npm", "bundled-\\\nnpm"); describe("Dockerfile RUN command discovery", () => { it("finds only executable unquoted npm command words in RUN instructions (#9933)", () => { diff --git a/test/platform/images/node-tar-dockerfile-contract.test.ts b/test/platform/images/node-tar-dockerfile-contract.test.ts index 292d2508b8d..baa6d7c350e 100644 --- a/test/platform/images/node-tar-dockerfile-contract.test.ts +++ b/test/platform/images/node-tar-dockerfile-contract.test.ts @@ -62,7 +62,7 @@ const dockerfiles = [ patchCount: 1, }, ] as const; -const patchCommand = "node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts"; +const patchCommand = "node /scripts/patch-bundled-npm-tar.mts"; const npmRootArguments = ["--npm-root", "/usr/local/lib/node_modules/npm"] as const; const hermesFinalArchivePath = "/tmp/nemoclaw-bundled-npm-tar.tgz"; const hermesFinalPatchArguments = [ @@ -482,7 +482,7 @@ describe("reviewed npm image remediation contract", () => { ); const upgradeRun = requireSingleReviewedDockerfileRunCommand( source, - "node --experimental-strip-types /scripts/upgrade-bundled-npm.mts", + "node /scripts/upgrade-bundled-npm.mts", npmRootArguments, ).commandStart; diff --git a/test/platform/images/protected-managed-image-build-script.test.ts b/test/platform/images/protected-managed-image-build-script.test.ts index 749b4641ce2..39ef180f88f 100644 --- a/test/platform/images/protected-managed-image-build-script.test.ts +++ b/test/platform/images/protected-managed-image-build-script.test.ts @@ -68,7 +68,7 @@ case "$*" in ;; npm-registry-dns-once:1 | npm-registry-dns-always:1 | npm-registry-dns-always:2) printf '%s\n' '#128 0.180 ERROR: curl failed: curl: (6) Could not resolve host: registry.npmjs.org' >&2 - printf '%s\n' 'ERROR: failed to build: failed to solve: process "/bin/sh -c node --experimental-strip-types /scripts/patch-bundled-npm-tar.mts --npm-root /usr/local/lib/node_modules/npm" did not complete successfully: exit code: 1' >&2 + printf '%s\n' 'ERROR: failed to build: failed to solve: process "/bin/sh -c node /scripts/patch-bundled-npm-tar.mts --npm-root /usr/local/lib/node_modules/npm" did not complete successfully: exit code: 1' >&2 exit 42 ;; npm-registry-dns-near-match:1) @@ -101,8 +101,8 @@ esac `#!/usr/bin/env bash set -euo pipefail printf '%s\n' "$*" >>"$NEMOCLAW_TEST_SEED_LOG" -mode="$4" -shift 4 +mode="$3" +shift 3 output="" while (($# > 0)); do case "$1" in diff --git a/test/repository/create-require-ratchet.test.ts b/test/repository/create-require-ratchet.test.ts index 9d6fba98942..8cae66c5a86 100644 --- a/test/repository/create-require-ratchet.test.ts +++ b/test/repository/create-require-ratchet.test.ts @@ -191,7 +191,7 @@ function runTrustedEntrypoint( repoRoot: string, environment: NodeJS.ProcessEnv, ) { - return spawnSync(process.execPath, ["--experimental-strip-types", entrypoint], { + return spawnSync(process.execPath, [entrypoint], { cwd: repoRoot, encoding: "utf8", env: { ...process.env, ...environment, GITHUB_WORKSPACE: repoRoot }, diff --git a/test/repository/shellcheck-json1-to-sarif.test.ts b/test/repository/shellcheck-json1-to-sarif.test.ts index b743213bb27..1ddef1b77ef 100644 --- a/test/repository/shellcheck-json1-to-sarif.test.ts +++ b/test/repository/shellcheck-json1-to-sarif.test.ts @@ -213,7 +213,7 @@ describe("ShellCheck JSON1 to SARIF conversion", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", HELPER_PATH, inputPath, outputPath], + [HELPER_PATH, inputPath, outputPath], { encoding: "utf-8" }, ); @@ -234,7 +234,7 @@ describe("ShellCheck JSON1 to SARIF conversion", () => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", HELPER_PATH, inputPath, outputPath], + [HELPER_PATH, inputPath, outputPath], { encoding: "utf-8" }, ); diff --git a/test/repository/stale-dist-check.test.ts b/test/repository/stale-dist-check.test.ts index b8fcf0fcdeb..c0eb6916b54 100644 --- a/test/repository/stale-dist-check.test.ts +++ b/test/repository/stale-dist-check.test.ts @@ -129,7 +129,7 @@ describe("stale-dist-check", () => { writeFile(path.join(root, "dist", "lib", "stale-dist-check.js"), "", 1_000_000); const runHook = () => - spawnSync(process.execPath, ["--experimental-strip-types", fixtureEntry], { + spawnSync(process.execPath, [fixtureEntry], { cwd: os.tmpdir(), encoding: "utf8", env: { ...process.env, NODE_OPTIONS: "" }, diff --git a/test/runtime/messaging/messaging-build-applier-credential-env.test.ts b/test/runtime/messaging/messaging-build-applier-credential-env.test.ts index 4de1943da8d..f827024dfd5 100644 --- a/test/runtime/messaging/messaging-build-applier-credential-env.test.ts +++ b/test/runtime/messaging/messaging-build-applier-credential-env.test.ts @@ -44,7 +44,7 @@ function runApplierProcess( ) { return spawnSync( "node", - ["--experimental-strip-types", SCRIPT_PATH, "--agent", agent, "--phase", phase], + [SCRIPT_PATH, "--agent", agent, "--phase", phase], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], env, timeout: 10_000 }, ); } diff --git a/test/runtime/messaging/messaging-build-applier-integrity.test.ts b/test/runtime/messaging/messaging-build-applier-integrity.test.ts index 14b91c14481..98fdd9a8fbd 100644 --- a/test/runtime/messaging/messaging-build-applier-integrity.test.ts +++ b/test/runtime/messaging/messaging-build-applier-integrity.test.ts @@ -109,7 +109,6 @@ describe("messaging-build-applier.mts: plugin archive integrity", () => { const result = spawnSync( process.execPath, [ - "--experimental-strip-types", "--input-type=module", "--eval", `await import(${JSON.stringify(pathToFileURL(stagedApplier).href)})`, @@ -327,7 +326,6 @@ describe("messaging-build-applier.mts: plugin archive integrity", () => { const result = spawnSync( "node", [ - "--experimental-strip-types", SCRIPT_PATH, "--agent", "openclaw", diff --git a/test/runtime/messaging/messaging-build-applier.test.ts b/test/runtime/messaging/messaging-build-applier.test.ts index ee2d827aa38..9404c0887a5 100644 --- a/test/runtime/messaging/messaging-build-applier.test.ts +++ b/test/runtime/messaging/messaging-build-applier.test.ts @@ -163,7 +163,6 @@ function runApplierProcess( return spawnSync( "node", [ - "--experimental-strip-types", SCRIPT_PATH, "--agent", agent, @@ -421,7 +420,6 @@ describe("messaging-build-applier.mts: agent-install", () => { const result = spawnSync( "node", [ - "--experimental-strip-types", SCRIPT_PATH, "--agent", agent, @@ -947,7 +945,7 @@ describe("messaging-build-applier.mts: agent-install", () => { fakeNode, [ "#!/bin/sh", - 'printf \'verify|%s|%s\\n\' "$3" "$4" >> "$OPENCLAW_TRACE"', + 'printf \'verify|%s|%s\\n\' "$2" "$3" >> "$OPENCLAW_TRACE"', "exit 0", "", ].join("\n"), @@ -1222,7 +1220,7 @@ describe("messaging-build-applier.mts: agent-install", () => { }, "openclaw", ); - const generatorResult = spawnSync("node", ["--experimental-strip-types", GENERATOR_PATH], { + const generatorResult = spawnSync("node", [GENERATOR_PATH], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], env: generatorEnv, diff --git a/test/security/fetch-guard-patch-regression.test.ts b/test/security/fetch-guard-patch-regression.test.ts index 403a5bf0a4b..3eccafd9f20 100644 --- a/test/security/fetch-guard-patch-regression.test.ts +++ b/test/security/fetch-guard-patch-regression.test.ts @@ -221,28 +221,28 @@ function runOpenClawUpgradeBlock(currentVersion: string) { "node() {", ' if [ "${1:-}" = "$postinstall_path" ]; then printf "node %s\\n" "$*" >> "$call_log"; return 0; fi', ' if [ "${1:-}" = "--input-type=module" ] && [ "${2:-}" = "-e" ] && printf "%s\\n" "${3:-}" | grep -q "StreamableHTTPServerTransport"; then printf "node %s\\n" "$*" >> "$call_log"; return 0; fi', - ' if [ "${2:-}" = "/scripts/lib/reviewed-npm-audit.mts" ]; then', - ' [ "$#" -eq 10 ] && [ "${1:-}" = "--experimental-strip-types" ] || return 87;', - ' [ "${3:-}" = "--directory" ] && [ "${4:-}" = "$mcporter_install" ] || return 88;', - ' [ "${5:-}" = "--exceptions" ] && [ "${6:-}" = "$audit_exceptions" ] || return 89;', - ' [ "${7:-}" = "--graph" ] && [ "${8:-}" = "mcporter-runtime" ] || return 90;', - ' [ "${9:-}" = "--threshold" ] && [ "${10:-}" = "high" ] || return 99;', + ' if [ "${1:-}" = "/scripts/lib/reviewed-npm-audit.mts" ]; then', + ' [ "$#" -eq 9 ] || return 87;', + ' [ "${2:-}" = "--directory" ] && [ "${3:-}" = "$mcporter_install" ] || return 88;', + ' [ "${4:-}" = "--exceptions" ] && [ "${5:-}" = "$audit_exceptions" ] || return 89;', + ' [ "${6:-}" = "--graph" ] && [ "${7:-}" = "mcporter-runtime" ] || return 90;', + ' [ "${8:-}" = "--threshold" ] && [ "${9:-}" = "high" ] || return 99;', ' printf "node %s\\n" "$*" >> "$call_log"; return 0;', " fi", - ' if [ "${2:-}" = "/scripts/lib/reviewed-npm-archive.mts" ]; then', - ' if [ "${3:-}" = "--verify-lock" ] || [ "${3:-}" = "--verify-installed-lock" ]; then return 0; fi', - ' if [ "${3:-}" = "--verify-only" ]; then', - ' [ "$#" -eq 11 ] && [ "${4:-}" = "--package-spec" ] && [ "${5:-}" = "mcporter@${MCPORTER_VERSION}" ] || return 91;', - ' [ "${6:-}" = "--integrity" ] && [ "${7:-}" = "$MCPORTER_0_7_3_INTEGRITY" ] || return 92;', - ' [ "${8:-}" = "--tarball-url" ] && [ "${9:-}" = "$MCPORTER_0_7_3_TARBALL" ] || return 93;', - ' [ "${10:-}" = "--label" ] && [ "${11:-}" = "mcporter ${MCPORTER_VERSION}" ] || return 94;', + ' if [ "${1:-}" = "/scripts/lib/reviewed-npm-archive.mts" ]; then', + ' if [ "${2:-}" = "--verify-lock" ] || [ "${2:-}" = "--verify-installed-lock" ]; then return 0; fi', + ' if [ "${2:-}" = "--verify-only" ]; then', + ' [ "$#" -eq 10 ] && [ "${3:-}" = "--package-spec" ] && [ "${4:-}" = "mcporter@${MCPORTER_VERSION}" ] || return 91;', + ' [ "${5:-}" = "--integrity" ] && [ "${6:-}" = "$MCPORTER_0_7_3_INTEGRITY" ] || return 92;', + ' [ "${7:-}" = "--tarball-url" ] && [ "${8:-}" = "$MCPORTER_0_7_3_TARBALL" ] || return 93;', + ' [ "${9:-}" = "--label" ] && [ "${10:-}" = "mcporter ${MCPORTER_VERSION}" ] || return 94;', " return 0;", " fi", - ' [ "$#" -eq 10 ] && [ "${3:-}" = "--package-spec" ] && [ "${4:-}" = "openclaw@${OPENCLAW_VERSION}" ] || return 95;', - ' [ "${5:-}" = "--integrity" ] && [ "${6:-}" = "$OPENCLAW_2026_7_1_INTEGRITY" ] || return 96;', - ' [ "${7:-}" = "--tarball-url" ] && [ "${8:-}" = "$OPENCLAW_2026_7_1_TARBALL" ] || return 97;', - ' [ "${9:-}" = "--label" ] && [ "${10:-}" = "OpenClaw ${OPENCLAW_VERSION}" ] || return 98;', - ' printf "npm pack %s --pack-destination reviewed-temp\\n" "${8:-}" >> "$call_log";', + ' [ "$#" -eq 9 ] && [ "${2:-}" = "--package-spec" ] && [ "${3:-}" = "openclaw@${OPENCLAW_VERSION}" ] || return 95;', + ' [ "${4:-}" = "--integrity" ] && [ "${5:-}" = "$OPENCLAW_2026_7_1_INTEGRITY" ] || return 96;', + ' [ "${6:-}" = "--tarball-url" ] && [ "${7:-}" = "$OPENCLAW_2026_7_1_TARBALL" ] || return 97;', + ' [ "${8:-}" = "--label" ] && [ "${9:-}" = "OpenClaw ${OPENCLAW_VERSION}" ] || return 98;', + ' printf "npm pack %s --pack-destination reviewed-temp\\n" "${7:-}" >> "$call_log";', ' printf "%s\\n" "$reviewed_archive"; return 0;', " fi", ' "$real_node" "$@"', @@ -422,7 +422,7 @@ describe("fetch-guard patch regression guard", () => { ); expect(invocation.calls).toContain("StreamableHTTPServerTransport"); expect(invocation.calls).toMatch( - /node --experimental-strip-types \/scripts\/lib\/reviewed-npm-audit\.mts --directory \S+ --exceptions \S+ --graph mcporter-runtime --threshold high/, + /node \/scripts\/lib\/reviewed-npm-audit\.mts --directory \S+ --exceptions \S+ --graph mcporter-runtime --threshold high/, ); expect(invocation.calls).not.toContain("audit signatures"); readRequiredMatch( diff --git a/test/security/mcporter-supply-chain.test.ts b/test/security/mcporter-supply-chain.test.ts index e48a3208400..c0f7e7afc6b 100644 --- a/test/security/mcporter-supply-chain.test.ts +++ b/test/security/mcporter-supply-chain.test.ts @@ -52,7 +52,7 @@ function extractIntegrityGate(contents: string): string { const startMarker = 'MCPORTER_EXPECTED_INTEGRITY=""'; const start = contents.indexOf(startMarker); const helperMarker = - "node --experimental-strip-types /scripts/lib/reviewed-npm-archive.mts --verify-only"; + "node /scripts/lib/reviewed-npm-archive.mts --verify-only"; const helperStart = contents.indexOf(helperMarker, start); const helperEndMarker = '--label "mcporter ${MCPORTER_VERSION}"'; const helperEnd = contents.indexOf(helperEndMarker, helperStart) + helperEndMarker.length; @@ -69,7 +69,7 @@ function extractIntegrityGate(contents: string): string { } function extractAuditReceiptInvocation(contents: string): string { - const startMarker = "node --experimental-strip-types /scripts/lib/npm-audit-receipt.mts"; + const startMarker = "node /scripts/lib/npm-audit-receipt.mts"; const endMarker = "--legacy-npmjs true"; const start = contents.indexOf(startMarker); const end = contents.indexOf(endMarker, start); @@ -89,14 +89,14 @@ function runIntegrityGate(contents: string, version: string) { `MCPORTER_0_7_3_TARBALL=${JSON.stringify(expectedTarball)}`, `npm() { printf '%s\\n' ${JSON.stringify(expectedIntegrity)}; }`, "node() {", - ' [ "$#" -eq 11 ] && [ "${1:-}" = "--experimental-strip-types" ] || return 81', - ' [ "${2:-}" = "/scripts/lib/reviewed-npm-archive.mts" ] && [ "${3:-}" = "--verify-only" ] || return 82', - ' [ "${4:-}" = "--package-spec" ] && [ "${5:-}" = "mcporter@${MCPORTER_VERSION}" ] || return 83', - ' [ "${6:-}" = "--integrity" ] && [ "${7:-}" = ' + + ' [ "$#" -eq 10 ] || return 81', + ' [ "${1:-}" = "/scripts/lib/reviewed-npm-archive.mts" ] && [ "${2:-}" = "--verify-only" ] || return 82', + ' [ "${3:-}" = "--package-spec" ] && [ "${4:-}" = "mcporter@${MCPORTER_VERSION}" ] || return 83', + ' [ "${5:-}" = "--integrity" ] && [ "${6:-}" = ' + `${JSON.stringify(expectedIntegrity)} ] || return 84`, - ' [ "${8:-}" = "--tarball-url" ] && [ "${9:-}" = ' + + ' [ "${7:-}" = "--tarball-url" ] && [ "${8:-}" = ' + `${JSON.stringify(expectedTarball)} ] || return 85`, - ' [ "${10:-}" = "--label" ] && [ "${11:-}" = "mcporter ${MCPORTER_VERSION}" ] || return 86', + ' [ "${9:-}" = "--label" ] && [ "${10:-}" = "mcporter ${MCPORTER_VERSION}" ] || return 86', "}", extractIntegrityGate(contents), "printf 'gate-passed\\n'", @@ -204,7 +204,7 @@ describe("mcporter image supply-chain controls", () => { ), ).toBe(true); expect(flattenedContents).toContain( - "node --experimental-strip-types /scripts/lib/reviewed-npm-audit.mts --directory /usr/local/lib/nemoclaw/mcporter-runtime --exceptions /scripts/npm-audit-exceptions.json --graph mcporter-runtime --threshold high", + "node /scripts/lib/reviewed-npm-audit.mts --directory /usr/local/lib/nemoclaw/mcporter-runtime --exceptions /scripts/npm-audit-exceptions.json --graph mcporter-runtime --threshold high", ); expect(contents).toContain("ARG NEMOCLAW_MCPORTER_AUDIT_RECEIPT_SHA256="); expect(contents).toContain( @@ -214,7 +214,7 @@ describe("mcporter image supply-chain controls", () => { "--mount=type=secret,id=nemoclaw-mcporter-audit-raw-report,required=false", ); expect(flattenedContents).toContain( - "node --experimental-strip-types /scripts/lib/npm-audit-receipt.mts --receipt", + "node /scripts/lib/npm-audit-receipt.mts --receipt", ); expect(flattenedContents).toContain( "--package-json /usr/local/lib/nemoclaw/mcporter-runtime/package.json --package-lock /usr/local/lib/nemoclaw/mcporter-runtime/package-lock.json --raw-report", diff --git a/test/security/security-c2-dockerfile-injection.test.ts b/test/security/security-c2-dockerfile-injection.test.ts index d01afb247e9..4d4d0e57959 100644 --- a/test/security/security-c2-dockerfile-injection.test.ts +++ b/test/security/security-c2-dockerfile-injection.test.ts @@ -135,7 +135,7 @@ describe("Gateway auth hardening: Dockerfile must not hardcode insecure auth def promoted = true; } if ( - /^RUN\s+(?:NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0\s+)?(?:NEMOCLAW_OPENCLAW_MANAGED_PROXY=0\s+)?node\s+--experimental-strip-types\s+\/scripts\/generate-openclaw-config\.mts$/.test( + /^RUN\s+(?:NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION=0\s+)?(?:NEMOCLAW_OPENCLAW_MANAGED_PROXY=0\s+)?node\s+\/scripts\/generate-openclaw-config\.mts$/.test( instruction.text, ) ) { diff --git a/test/skills/check-gates-test-fixtures.ts b/test/skills/check-gates-test-fixtures.ts index 6a5b8722232..05e00549394 100644 --- a/test/skills/check-gates-test-fixtures.ts +++ b/test/skills/check-gates-test-fixtures.ts @@ -814,7 +814,6 @@ esac [ "--import", clockPath, - "--experimental-strip-types", "--no-warnings", ".agents/skills/nemoclaw-maintainer-day/scripts/check-gates.ts", "42", diff --git a/test/skills/triage-runtime.test.ts b/test/skills/triage-runtime.test.ts index 364063a6dcb..01fada21663 100644 --- a/test/skills/triage-runtime.test.ts +++ b/test/skills/triage-runtime.test.ts @@ -123,7 +123,6 @@ if (args[0] === "api" && args[1] === "--paginate" && args[2]?.startsWith("repos/ fs.chmodSync(ghPath, 0o755); const args = [ - "--experimental-strip-types", "--no-warnings", ".agents/skills/nemoclaw-maintainer-day/scripts/triage.ts", "--limit", diff --git a/tools/e2e/openshell-gateway-auth-artifact-safety.mts b/tools/e2e/openshell-gateway-auth-artifact-safety.mts index 1c13378b525..4537deb788f 100644 --- a/tools/e2e/openshell-gateway-auth-artifact-safety.mts +++ b/tools/e2e/openshell-gateway-auth-artifact-safety.mts @@ -435,7 +435,7 @@ function runCli(): void { const [rootDir, ...extra] = process.argv.slice(2); if (!rootDir || extra.length > 0) { throw new Error( - "Usage: node --experimental-strip-types tools/e2e/openshell-gateway-auth-artifact-safety.mts ", + "Usage: node tools/e2e/openshell-gateway-auth-artifact-safety.mts ", ); } const approvedRoot = scanAndApproveOpenShellGatewayAuthArtifacts(rootDir); diff --git a/tools/e2e/openshell-gateway-auth-contract-workflow-boundary.mts b/tools/e2e/openshell-gateway-auth-contract-workflow-boundary.mts index 10b5245d463..7a59efde1b5 100644 --- a/tools/e2e/openshell-gateway-auth-contract-workflow-boundary.mts +++ b/tools/e2e/openshell-gateway-auth-contract-workflow-boundary.mts @@ -23,7 +23,7 @@ const ARTIFACT_SAFETY_GATED_UPLOAD = "${{ always() && steps.artifact_safety.outcome == 'success' && steps.artifact_safety.outputs.approved_path != '' }}"; const APPROVED_ARTIFACT_PATH = "${{ steps.artifact_safety.outputs.approved_path }}"; const ARTIFACT_SAFETY_COMMAND = - 'node --experimental-strip-types --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR"'; + 'node --no-warnings tools/e2e/openshell-gateway-auth-artifact-safety.mts "$E2E_ARTIFACT_DIR"'; type WorkflowStep = { env?: Record; diff --git a/tools/e2e/operations-workflow-boundary.mts b/tools/e2e/operations-workflow-boundary.mts index 8eb1101e8be..d51cc8ccce8 100644 --- a/tools/e2e/operations-workflow-boundary.mts +++ b/tools/e2e/operations-workflow-boundary.mts @@ -52,7 +52,7 @@ const PR_MANAGED_IMAGE_RESOLVER_SCRIPT = " exit 1", " }", "fi", - 'selection="$(node --experimental-strip-types --no-warnings tools/e2e/pr-managed-image-publication.mts "$catalog_path")"', + 'selection="$(node --no-warnings tools/e2e/pr-managed-image-publication.mts "$catalog_path")"', 'case "$selection" in', " base-cohort)", ' [[ ! -e "$catalog_path" && ! -L "$catalog_path" ]] || {', @@ -798,7 +798,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): 'if [[ "$SELECT_NEAREST_SUCCESSFUL_PUBLICATION" == "1" ]]; then', " wait_seconds=300", "fi", - 'node --experimental-strip-types --no-warnings tools/e2e/base-image-publication.mts --wait-seconds "$wait_seconds" --poll-seconds 30', + 'node --no-warnings tools/e2e/base-image-publication.mts --wait-seconds "$wait_seconds" --poll-seconds 30', "", ].join("\n"), }, @@ -811,7 +811,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): PUBLICATION_RUN_ATTEMPT: "${{ steps.publication.outputs.run_attempt }}", PUBLICATION_RUN_ID: "${{ steps.publication.outputs.run_id }}", }, - run: 'node --experimental-strip-types --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/dcode-base-contract"', + run: 'node --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/dcode-base-contract"', }, { id: "validate_dcode_base", @@ -822,7 +822,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): PUBLICATION_RUN_ATTEMPT: "${{ steps.publication.outputs.run_attempt }}", PUBLICATION_RUN_ID: "${{ steps.publication.outputs.run_id }}", }, - run: 'node --experimental-strip-types --no-warnings tools/e2e/dcode-base-image-contract.mts "${RUNNER_TEMP}/dcode-base-contract/contract.json"', + run: 'node --no-warnings tools/e2e/dcode-base-image-contract.mts "${RUNNER_TEMP}/dcode-base-contract/contract.json"', }, { id: "download_managed_cohort", @@ -835,7 +835,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): PUBLICATION_RUN_ATTEMPT: "${{ steps.publication.outputs.run_attempt }}", PUBLICATION_RUN_ID: "${{ steps.publication.outputs.run_id }}", }, - run: 'node --experimental-strip-types --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/managed-image-cohort"', + run: 'node --no-warnings tools/e2e/exact-artifact-download.mts "${RUNNER_TEMP}/managed-image-cohort"', }, { id: "validate_managed_cohort", @@ -846,7 +846,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): PUBLICATION_RUN_ATTEMPT: "${{ steps.publication.outputs.run_attempt }}", PUBLICATION_RUN_ID: "${{ steps.publication.outputs.run_id }}", }, - run: 'node --experimental-strip-types --no-warnings tools/e2e/managed-image-cohort-contract.mts "${RUNNER_TEMP}/managed-image-cohort/cohort.json"', + run: 'node --no-warnings tools/e2e/managed-image-cohort-contract.mts "${RUNNER_TEMP}/managed-image-cohort/cohort.json"', }, ], }; @@ -1134,7 +1134,7 @@ function validateRelevantE2e(errors: string[], workflow: OperationsWorkflow): vo requireResults.env?.RELEASE_REQUIRED_JOBS !== "${{ needs.generate-matrix.outputs.selected_workflow_jobs }}" || requireResults.run !== - "node --experimental-strip-types --no-warnings tools/e2e/release-qualification.mts" + "node --no-warnings tools/e2e/release-qualification.mts" ) { errors.push("relevant-e2e must evaluate planner-selected jobs from needs"); } @@ -1177,7 +1177,7 @@ function validateReleaseQualification(errors: string[], workflow: OperationsWork requireResults.env?.RELEASE_REQUIRED_JOBS !== "${{ needs.generate-matrix.outputs.release_required_jobs }}" || requireResults.run !== - "node --experimental-strip-types --no-warnings tools/e2e/release-qualification.mts" + "node --no-warnings tools/e2e/release-qualification.mts" ) { errors.push("release-qualification must evaluate planner-selected jobs from needs"); } diff --git a/tools/e2e/target-catalogue.mts b/tools/e2e/target-catalogue.mts index e5c433f2a88..8174d74fc4b 100644 --- a/tools/e2e/target-catalogue.mts +++ b/tools/e2e/target-catalogue.mts @@ -1797,7 +1797,7 @@ export async function runCatalogueTarget(id: string, testFile: string): Promise< const runPressureCommand = (command: string): void => { const result = spawnSync( process.execPath, - ["--experimental-strip-types", "--no-warnings", "tools/e2e/runner-pressure.mts", command], + ["--no-warnings", "tools/e2e/runner-pressure.mts", command], { env: process.env, stdio: "inherit", timeout: 60_000 }, ); if (result.error) throw result.error; diff --git a/tools/e2e/workflow-boundary.mts b/tools/e2e/workflow-boundary.mts index bab8a19c8ac..034fa234dbb 100644 --- a/tools/e2e/workflow-boundary.mts +++ b/tools/e2e/workflow-boundary.mts @@ -1992,7 +1992,7 @@ function validateJetsonControllerBoundary(errors: string[], jobs: WorkflowRecord const dispatch = namedStep(steps, "Dispatch exact commit to Jetson through operator backend"); if ( dispatch?.run !== - "node --experimental-strip-types --no-warnings tools/e2e/jetson-dispatch-client.mts" || + "node --no-warnings tools/e2e/jetson-dispatch-client.mts" || !isDeepStrictEqual(asRecord(dispatch?.env), { E2E_ARTIFACT_DIR: "${{ runner.temp }}/e2e-artifacts/live/jetson-nvmap-gpu", JETSON_DISPATCH_CANDIDATE_SHA: "${{ inputs.checkout_sha || github.sha }}", diff --git a/tools/mcp-tool-discovery-runtime/package.json b/tools/mcp-tool-discovery-runtime/package.json index ab016185027..ac521999f60 100644 --- a/tools/mcp-tool-discovery-runtime/package.json +++ b/tools/mcp-tool-discovery-runtime/package.json @@ -24,10 +24,10 @@ "node": ">=22.19.0" }, "scripts": { - "bundle": "node --experimental-strip-types build-runtime.ts", - "bundle:reviewed": "node --experimental-strip-types build-reviewed-runtime.ts", - "bundle:reviewed:check": "node --experimental-strip-types build-reviewed-runtime.ts --check", - "test": "node --experimental-strip-types --test streamable-http-client.test.ts", + "bundle": "node build-runtime.ts", + "bundle:reviewed": "node build-reviewed-runtime.ts", + "bundle:reviewed:check": "node build-reviewed-runtime.ts --check", + "test": "node --test streamable-http-client.test.ts", "typecheck": "tsc -p tsconfig.json" } } diff --git a/tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle b/tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle index b965fa88753..af207af0178 100644 --- a/tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle +++ b/tools/mcp-tool-discovery-runtime/reviewed-runtime-bundle/managed-startup-image-runtime.bundle @@ -5,7 +5,7 @@ except urllib.error.HTTPError as error: print(error.code)"`]}}],render:[{id:"dis `;if(Buffer.byteLength(serialized,"utf8")>MANAGED_STARTUP_ROOT_APPLY_MAX_BYTES){fail3("serialized request exceeds its bounded transport")}return serialized}function parseManagedStartupRootApplyRequest(text){if(text.length===0||Buffer.byteLength(text,"utf8")>MANAGED_STARTUP_ROOT_APPLY_MAX_BYTES){fail3("serialized request is empty or too large")}let parsed;try{parsed=JSON.parse(text)}catch{fail3("serialized request is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail3("serialized request must be an object")}const record=parsed;const expectedKeys=["agent","corporateCaB64","encodedProfile","profileFingerprint","schemaVersion"];if(Object.keys(record).sort().join(",")!==expectedKeys.sort().join(",")||record.schemaVersion!==MANAGED_STARTUP_ROOT_APPLY_SCHEMA_VERSION||typeof record.encodedProfile!=="string"||typeof record.profileFingerprint!=="string"||record.corporateCaB64!==null&&typeof record.corporateCaB64!=="string"){fail3("serialized request has an invalid schema")}const request=createManagedStartupRootApplyRequest({agent:exactAgent(record.agent),encodedProfile:record.encodedProfile,...record.corporateCaB64===null?{}:{corporateCaB64:record.corporateCaB64}});if(record.profileFingerprint!==request.profileFingerprint||!SHA256_RE3.test(record.profileFingerprint)){fail3("profile fingerprint does not match the encoded profile")}if(serializeManagedStartupRootApplyRequest(request)!==text){fail3("serialized request is not canonical")}return request}var import_node_crypto5=require("node:crypto");var import_node_fs2=__toESM(require("node:fs"));var import_node_path2=__toESM(require("node:path"));var MANAGED_HERMES_STATE_ROOT="/sandbox/.hermes";var MANAGED_OPENCLAW_STATE_ROOT="/sandbox/.openclaw";var HERMES_STATE_VOLUME_NAME_PREFIX="nemoclaw-hermes-state-v1";var OPENCLAW_STATE_VOLUME_NAME_PREFIX="nemoclaw-openclaw-state-v1";var MANAGED_AGENT_STATE_ROOTS=Object.freeze({openclaw:Object.freeze([Object.freeze({mountTarget:MANAGED_OPENCLAW_STATE_ROOT,resourceIdentity:sandboxName=>`${OPENCLAW_STATE_VOLUME_NAME_PREFIX}-${sandboxName}`,ownershipLabels:(sandboxName,mountTarget)=>Object.freeze({"io.nvidia.nemoclaw.openclaw-state.managed":"true","io.nvidia.nemoclaw.openclaw-state.schema":"1","io.nvidia.nemoclaw.openclaw-state.sandbox":sandboxName,"io.nvidia.nemoclaw.openclaw-state.target":mountTarget}),uidAuthority:"agent",gidAuthority:"agent",mode:1528,readWrite:true})]),hermes:Object.freeze([Object.freeze({mountTarget:MANAGED_HERMES_STATE_ROOT,resourceIdentity:sandboxName=>`${HERMES_STATE_VOLUME_NAME_PREFIX}-${sandboxName}`,ownershipLabels:(sandboxName,mountTarget)=>Object.freeze({"io.nvidia.nemoclaw.hermes-state.managed":"true","io.nvidia.nemoclaw.hermes-state.schema":"1","io.nvidia.nemoclaw.hermes-state.sandbox":sandboxName,"io.nvidia.nemoclaw.hermes-state.target":mountTarget}),uidAuthority:"agent",gidAuthority:"agent",mode:2040,readWrite:true})]),"langchain-deepagents-code":Object.freeze([]),pi:Object.freeze([])});function managedStartupStateRootMountTargets(agent){return Object.freeze(MANAGED_AGENT_STATE_ROOTS[agent].map(({mountTarget})=>mountTarget))}var MANAGED_AGENT_WORKSPACE_ROOTS=Object.freeze({openclaw:Object.freeze({uidAuthority:"agent",gidAuthority:"agent",mode:493}),hermes:Object.freeze({uidAuthority:"agent",gidAuthority:"agent",mode:493}),"langchain-deepagents-code":Object.freeze({uidAuthority:"root",gidAuthority:"agent",mode:1021}),pi:Object.freeze({uidAuthority:"agent",gidAuthority:"agent",mode:493})});var TRANSACTION_SCHEMA_VERSION=1;var MAX_TRANSACTION_FILES=128;var MAX_TRANSACTION_FILE_BYTES=8*1024*1024;var MAX_TRANSACTION_TOTAL_BYTES=32*1024*1024;var MAX_MANIFEST_BYTES=256*1024;var MAX_COMMIT_RECEIPT_BYTES=4096;var TRANSACTION_PARENT_DIRECTORY_MODE=493;var TRANSACTION_DIRECTORY_MODE=448;var TRANSACTION_FILE_MODE=256;var ATOMIC_TEMPORARY_FILE_MODE=384;var MANAGED_STARTUP_SHARED_TRANSACTION_DIRECTORY="/var/lib/nemoclaw/managed-startup-shared-state-transaction-v1";var MANAGED_STARTUP_SHARED_ROLLBACK_RECEIPT_DIRECTORY="/run/nemoclaw/managed-startup-shared-rollback-receipt-v1";var MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_DIRECTORY="/var/lib/nemoclaw/managed-startup-shared-state-commit-v1";var MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE="receipt.json";function fail4(message){throw new Error(`Managed startup shared-state transaction failed: ${message}`)}function resolveOptions(options={}){const sandboxRoot=import_node_path2.default.resolve(options.sandboxRoot??"/sandbox");const transactionDirectory=import_node_path2.default.resolve(options.transactionDirectory??MANAGED_STARTUP_SHARED_TRANSACTION_DIRECTORY);const commitReceiptDirectory=import_node_path2.default.resolve(options.commitReceiptDirectory??(options.transactionDirectory?import_node_path2.default.join(import_node_path2.default.dirname(transactionDirectory),import_node_path2.default.basename(MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_DIRECTORY)):MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_DIRECTORY));if(transactionDirectory===sandboxRoot||transactionDirectory.startsWith(`${sandboxRoot}${import_node_path2.default.sep}`)||commitReceiptDirectory===sandboxRoot||commitReceiptDirectory.startsWith(`${sandboxRoot}${import_node_path2.default.sep}`)||import_node_path2.default.dirname(commitReceiptDirectory)!==import_node_path2.default.dirname(transactionDirectory)||commitReceiptDirectory===transactionDirectory){fail4("transaction and commit receipts require distinct paths outside sandbox-shared state")}const bootstrapIdentity=options.bootstrapIdentity??null;if(bootstrapIdentity!==null&&!/^[a-f0-9]{64}$/u.test(bootstrapIdentity)){fail4("bootstrap identity must encode 32 lowercase-hex bytes")}return{sandboxRoot,transactionParentDirectory:import_node_path2.default.dirname(transactionDirectory),transactionDirectory,backupDirectory:import_node_path2.default.join(transactionDirectory,"backups"),manifestFile:import_node_path2.default.join(transactionDirectory,"manifest.json"),commitReceiptDirectory,commitReceiptFile:import_node_path2.default.join(commitReceiptDirectory,MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE),trustedUid:options.trustedUid??0,trustedGid:options.trustedGid??0,readOnlyReceipt:options.readOnlyReceipt??false,bootstrapIdentity}}function modeOf2(stat){if(typeof stat.mode==="bigint"){return Number(stat.mode&0o7777n)}return stat.mode&4095}function requireTransactionIdentity(options){const expectedUid=options.readOnlyReceipt?0:options.trustedUid;const expectedGid=options.readOnlyReceipt?0:options.trustedGid;if(process.geteuid?.()!==expectedUid||process.getegid?.()!==expectedGid){fail4("transaction control requires the trusted effective identity")}}function pathExistsNoFollow(target){try{import_node_fs2.default.lstatSync(target);return true}catch(error){if(error.code==="ENOENT")return false;fail4(`could not inspect ${target}`)}}function requireDirectory(target,options,expectedMode=null){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch{fail4(`required directory is missing: ${target}`)}if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`required directory is unsafe: ${target}`)}if(expectedMode!==null&&(stat.uid!==options.trustedUid||stat.gid!==options.trustedGid||modeOf2(stat)!==expectedMode)){fail4(`${target} must be ${options.trustedUid}:${options.trustedGid} mode ${expectedMode.toString(8)}`)}return stat}function requireTransactionBoundaries(options){requireDirectory(options.sandboxRoot,options);requireDirectory(options.transactionParentDirectory,options,TRANSACTION_PARENT_DIRECTORY_MODE)}function sameStableMetadata(left,right){return left.dev===right.dev&&left.ino===right.ino&&left.mode===right.mode&&left.nlink===right.nlink&&left.uid===right.uid&&left.gid===right.gid&&left.size===right.size&&left.mtimeNs===right.mtimeNs&&left.ctimeNs===right.ctimeNs}function readStableFile(target,maxBytes){const noFollow=import_node_fs2.default.constants.O_NOFOLLOW;if(typeof noFollow!=="number")fail4("O_NOFOLLOW is unavailable");let descriptor;try{descriptor=import_node_fs2.default.openSync(target,import_node_fs2.default.constants.O_RDONLY|noFollow)}catch{fail4(`could not safely open ${target}`)}try{const before=import_node_fs2.default.fstatSync(descriptor,{bigint:true});if(!before.isFile()||before.nlink!==1n||before.size<0n||before.size>BigInt(maxBytes)){fail4(`refusing unsafe or oversized transaction file ${target}`)}const bytes=Buffer.alloc(Number(before.size));let offset=0;while(offset!segment||segment==="."||segment==="..")){fail4(`unsafe transaction path ${JSON.stringify(value)}`)}return segments.join("/")}function absoluteTarget(relativePath,options){const safe=safeRelativePath(relativePath);const target=import_node_path2.default.resolve(options.sandboxRoot,safe);if(!target.startsWith(`${options.sandboxRoot}${import_node_path2.default.sep}`)){fail4(`transaction target escapes the sandbox root: ${relativePath}`)}return target}function relativeTarget(target,options){return safeRelativePath(import_node_path2.default.relative(options.sandboxRoot,target))}function isDeclaredAgentStateRoot(expectedAgent,outputRoot,options){const relative=import_node_path2.default.relative(options.sandboxRoot,outputRoot).split(import_node_path2.default.sep).join("/");const canonicalTarget=import_node_path2.default.posix.join("/sandbox",relative);return managedStartupStateRootMountTargets(expectedAgent).includes(canonicalTarget)}function validateExistingAncestors(target,expectedAgent,options){const relative=relativeTarget(target,options);const sandboxStat=requireDirectory(options.sandboxRoot,options);const outputRoot=agentRoot(expectedAgent,options.sandboxRoot);if(target!==outputRoot&&!target.startsWith(`${outputRoot}${import_node_path2.default.sep}`)){fail4(`transaction target escapes the ${expectedAgent} state root: ${target}`)}let current=options.sandboxRoot;let expectedDevice=sandboxStat.dev;const segments=relative.split("/").slice(0,-1);for(const segment of segments){current=import_node_path2.default.join(current,segment);let stat;try{stat=import_node_fs2.default.lstatSync(current)}catch(error){if(error.code==="ENOENT")return;fail4(`could not inspect transaction path ancestor ${current}`)}if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`transaction path ancestor is unsafe: ${current}`)}if(current===outputRoot&&isDeclaredAgentStateRoot(expectedAgent,outputRoot,options)){expectedDevice=stat.dev}else if(stat.dev!==expectedDevice){fail4(`transaction path crosses a nested filesystem mount: ${current}`)}}}function managedOutputDevice(expectedAgent,options){const sandboxStat=requireDirectory(options.sandboxRoot,options);const outputRoot=agentRoot(expectedAgent,options.sandboxRoot);let stat;try{stat=import_node_fs2.default.lstatSync(outputRoot)}catch(error){if(error.code==="ENOENT")return sandboxStat.dev;fail4(`could not inspect managed output root ${outputRoot}`)}if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`managed output root is unsafe: ${outputRoot}`)}if(!isDeclaredAgentStateRoot(expectedAgent,outputRoot,options)&&stat.dev!==sandboxStat.dev){fail4(`managed output root crosses a nested filesystem mount: ${outputRoot}`)}return stat.dev}function agentRoot(agent,sandboxRoot){switch(agent){case"openclaw":return import_node_path2.default.join(sandboxRoot,".openclaw");case"hermes":return import_node_path2.default.join(sandboxRoot,".hermes");case"langchain-deepagents-code":return import_node_path2.default.join(sandboxRoot,".deepagents");case"pi":return import_node_path2.default.join(sandboxRoot,".pi")}}function resolveUnderAgentRoot(root,relativePath){const safe=safeRelativePath(relativePath);const target=import_node_path2.default.resolve(root,safe);if(!target.startsWith(`${root}${import_node_path2.default.sep}`)){fail4(`managed output escapes the agent root: ${relativePath}`)}return target}function renderTarget(root,agent,target){if(agent==="openclaw"&&target==="openclaw.json"){return import_node_path2.default.join(root,"openclaw.json")}const prefix=agent==="openclaw"?"~/.openclaw/":agent==="hermes"?"~/.hermes/":null;if(!prefix||!target.startsWith(prefix)){fail4(`unsupported managed messaging render target ${JSON.stringify(target)}`)}return resolveUnderAgentRoot(root,target.slice(prefix.length))}function managedOutputTargets(profile,options){const root=agentRoot(profile.agent,options.sandboxRoot);const files=new Set;const directories=new Set([root]);switch(profile.agent){case"openclaw":files.add(import_node_path2.default.join(root,"openclaw.json"));files.add(import_node_path2.default.join(root,".config-hash"));break;case"hermes":files.add(import_node_path2.default.join(root,"config.yaml"));files.add(import_node_path2.default.join(root,".env"));files.add(import_node_path2.default.join(root,".config-hash"));break;case"langchain-deepagents-code":files.add(import_node_path2.default.join(root,"config.toml"));directories.add(import_node_path2.default.join(root,".state"));break;case"pi":directories.add(import_node_path2.default.join(root,"agent"));files.add(import_node_path2.default.join(root,"agent","models.json"));break}if(profile.messaging.plan!==null){const plan=parseSandboxMessagingPlan(profile.messaging.plan,{agent:profile.agent});if(!plan)fail4("managed messaging plan is invalid");for(const render of selectEnabledMessagingAgentRender(plan)){if(typeof render.target!=="string")continue;files.add(renderTarget(root,profile.agent,render.target))}for(const step of selectEnabledPostAgentInstallBuildFiles(plan)){if(typeof step.value!=="object"||step.value===null){continue}const outputPath=step.value.path;if(typeof outputPath==="string"){files.add(resolveUnderAgentRoot(root,outputPath))}}}for(const file of files){let parent=import_node_path2.default.dirname(file);while(parent!==options.sandboxRoot&&parent.startsWith(`${root}${import_node_path2.default.sep}`)){directories.add(parent);if(parent===root)break;parent=import_node_path2.default.dirname(parent)}}return{files:[...files].sort(),directories:[...directories].sort((left,right)=>left.split(import_node_path2.default.sep).length-right.split(import_node_path2.default.sep).length)}}function snapshotFile(target,index,expectedAgent,options){validateExistingAncestors(target,expectedAgent,options);let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT"){return{receipt:{path:relativeTarget(target,options),state:"absent"},bytes:null}}fail4(`could not inspect managed output ${target}`)}if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1){fail4(`managed output is not a safe regular file: ${target}`)}if(stat.dev!==managedOutputDevice(expectedAgent,options)){fail4(`managed output crosses a nested filesystem mount: ${target}`)}const stable=readStableFile(target,MAX_TRANSACTION_FILE_BYTES);const size=Number(stable.stat.size);const backup=`${String(index).padStart(3,"0")}.bin`;return{receipt:{path:relativeTarget(target,options),state:"file",backup,sha256:(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex"),size,uid:Number(stable.stat.uid),gid:Number(stable.stat.gid),mode:Number(stable.stat.mode&0o7777n)},bytes:stable.bytes}}function snapshotDirectory(target,expectedAgent,options){validateExistingAncestors(import_node_path2.default.join(target,".receipt"),expectedAgent,options);let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT"){return{path:relativeTarget(target,options),state:"absent"}}fail4(`could not inspect managed output directory ${target}`)}if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`managed output directory is unsafe: ${target}`)}if(stat.dev!==managedOutputDevice(expectedAgent,options)){fail4(`managed output directory crosses a nested filesystem mount: ${target}`)}return{path:relativeTarget(target,options),state:"directory",uid:stat.uid,gid:stat.gid,mode:modeOf2(stat)}}function atomicWriteTrustedFile(target,contents,mode,uid,gid){const parent=import_node_path2.default.dirname(target);const temporary=import_node_path2.default.join(parent,`.${import_node_path2.default.basename(target)}.${(0,import_node_crypto5.randomBytes)(12).toString("hex")}`);let descriptor;try{descriptor=import_node_fs2.default.openSync(temporary,import_node_fs2.default.constants.O_CREAT|import_node_fs2.default.constants.O_EXCL|import_node_fs2.default.constants.O_WRONLY|import_node_fs2.default.constants.O_NOFOLLOW,384);import_node_fs2.default.writeFileSync(descriptor,contents);import_node_fs2.default.fchownSync(descriptor,uid,gid);import_node_fs2.default.fchmodSync(descriptor,mode);import_node_fs2.default.fsyncSync(descriptor);import_node_fs2.default.closeSync(descriptor);descriptor=void 0;import_node_fs2.default.renameSync(temporary,target)}catch(error){if(descriptor!==void 0)import_node_fs2.default.closeSync(descriptor);try{import_node_fs2.default.unlinkSync(temporary)}catch{}fail4(`could not atomically write ${target}: ${error.message}`)}}function fsyncDirectory(directory){const descriptor=import_node_fs2.default.openSync(directory,import_node_fs2.default.constants.O_RDONLY);try{import_node_fs2.default.fsyncSync(descriptor)}finally{import_node_fs2.default.closeSync(descriptor)}}function canonicalManifest(manifest){return`${JSON.stringify(manifest,null,2)} `}function canonicalLegacyManifest(manifest){return`${JSON.stringify({schemaVersion:manifest.schemaVersion,agent:manifest.agent,profileFingerprint:manifest.profileFingerprint,files:manifest.files,directories:manifest.directories},null,2)} `}function canonicalCommitReceipt(receipt){return`${JSON.stringify(receipt,null,2)} -`}function requireExactKeys(record,keys){if(Object.keys(record).sort().join(",")!==[...keys].sort().join(",")){fail4("transaction manifest contains unexpected fields")}}function parseCommitReceipt(text){let parsed;try{parsed=JSON.parse(text)}catch{fail4("commit receipt is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail4("commit receipt must be an object")}const record=parsed;requireExactKeys(record,["agent","bootstrapIdentity","profileFingerprint","schemaVersion"]);if(record.schemaVersion!==TRANSACTION_SCHEMA_VERSION||!MANAGED_STARTUP_AGENTS.includes(String(record.agent))||typeof record.profileFingerprint!=="string"||!/^[a-f0-9]{64}$/u.test(record.profileFingerprint)||typeof record.bootstrapIdentity!=="string"||!/^[a-f0-9]{64}$/u.test(record.bootstrapIdentity)){fail4("commit receipt has an invalid envelope")}const receipt={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:record.agent,profileFingerprint:record.profileFingerprint,bootstrapIdentity:record.bootstrapIdentity};if(canonicalCommitReceipt(receipt)!==text){fail4("commit receipt is not canonical")}return receipt}function safeMetadata(value){return Number.isSafeInteger(value)&&value>=0}function parseManifest(text){let parsed;try{parsed=JSON.parse(text)}catch{fail4("transaction manifest is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail4("transaction manifest must be an object")}const record=parsed;const hasBootstrapIdentity=Object.hasOwn(record,"bootstrapIdentity");requireExactKeys(record,hasBootstrapIdentity?["agent","bootstrapIdentity","directories","files","profileFingerprint","schemaVersion"]:["agent","directories","files","profileFingerprint","schemaVersion"]);const bootstrapIdentity=hasBootstrapIdentity?record.bootstrapIdentity:null;if(record.schemaVersion!==TRANSACTION_SCHEMA_VERSION||!MANAGED_STARTUP_AGENTS.includes(String(record.agent))||typeof record.profileFingerprint!=="string"||!/^[a-f0-9]{64}$/u.test(record.profileFingerprint)||!(bootstrapIdentity===null||typeof bootstrapIdentity==="string"&&/^[a-f0-9]{64}$/u.test(bootstrapIdentity))||!Array.isArray(record.files)||!Array.isArray(record.directories)||record.files.length>MAX_TRANSACTION_FILES||record.directories.length>MAX_TRANSACTION_FILES*4){fail4("transaction manifest has an invalid envelope")}const files=record.files.map(value=>{if(typeof value!=="object"||value===null||Array.isArray(value)){return fail4("transaction file receipt must be an object")}const receipt=value;if(typeof receipt.path!=="string"){return fail4("transaction file receipt path must be a string")}const receiptPath=safeRelativePath(receipt.path);if(receipt.state==="absent"){requireExactKeys(receipt,["path","state"]);return{path:receiptPath,state:"absent"}}requireExactKeys(receipt,["backup","gid","mode","path","sha256","size","state","uid"]);if(receipt.state!=="file"||typeof receipt.backup!=="string"||!/^[0-9]{3}\.bin$/u.test(receipt.backup)||typeof receipt.sha256!=="string"||!/^[a-f0-9]{64}$/u.test(receipt.sha256)||!safeMetadata(receipt.size)||receipt.size>MAX_TRANSACTION_FILE_BYTES||!safeMetadata(receipt.uid)||!safeMetadata(receipt.gid)||!safeMetadata(receipt.mode)||receipt.mode>4095){return fail4("transaction file receipt is invalid")}return{path:receiptPath,state:"file",backup:receipt.backup,sha256:receipt.sha256,size:receipt.size,uid:receipt.uid,gid:receipt.gid,mode:receipt.mode}});const directories=record.directories.map(value=>{if(typeof value!=="object"||value===null||Array.isArray(value)){return fail4("transaction directory receipt must be an object")}const receipt=value;if(typeof receipt.path!=="string"){return fail4("transaction directory receipt path must be a string")}const receiptPath=safeRelativePath(receipt.path);if(receipt.state==="absent"){requireExactKeys(receipt,["path","state"]);return{path:receiptPath,state:"absent"}}requireExactKeys(receipt,["gid","mode","path","state","uid"]);if(receipt.state!=="directory"||!safeMetadata(receipt.uid)||!safeMetadata(receipt.gid)||!safeMetadata(receipt.mode)||receipt.mode>4095){return fail4("transaction directory receipt is invalid")}return{path:receiptPath,state:"directory",uid:receipt.uid,gid:receipt.gid,mode:receipt.mode}});const filePaths=files.map(receipt=>receipt.path);const directoryPaths=directories.map(receipt=>receipt.path);const backupNames=files.filter(receipt=>receipt.state==="file").map(receipt=>receipt.backup);if(new Set(filePaths).size!==filePaths.length||new Set(directoryPaths).size!==directoryPaths.length||new Set(backupNames).size!==backupNames.length){fail4("transaction manifest contains duplicate receipts")}const manifest={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:record.agent,profileFingerprint:record.profileFingerprint,bootstrapIdentity,files,directories};const canonical=hasBootstrapIdentity?canonicalManifest(manifest):canonicalLegacyManifest(manifest);if(canonical!==text){fail4("transaction manifest is not canonical")}return manifest}function requireTrustedTransactionPath(target,mode,options){const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||(mode===TRANSACTION_DIRECTORY_MODE?!stat.isDirectory():!stat.isFile())||!options.readOnlyReceipt&&(stat.uid!==options.trustedUid||stat.gid!==options.trustedGid)||modeOf2(stat)!==mode){fail4(`transaction artifact has unsafe metadata: ${target}`)}}function requireReadOnlyReceiptMount(target,options){if(!options.readOnlyReceipt)return;const probe=import_node_path2.default.join(target,".nemoclaw-write-probe");let descriptor;try{descriptor=import_node_fs2.default.openSync(probe,import_node_fs2.default.constants.O_CREAT|import_node_fs2.default.constants.O_EXCL|import_node_fs2.default.constants.O_WRONLY|import_node_fs2.default.constants.O_NOFOLLOW,384);import_node_fs2.default.closeSync(descriptor);descriptor=void 0;import_node_fs2.default.unlinkSync(probe)}catch(error){if(descriptor!==void 0)import_node_fs2.default.closeSync(descriptor);if(error.code==="EROFS")return;fail4("copied receipt must be mounted on a read-only filesystem")}fail4("copied receipt mount is writable")}function loadManifest(options){requireTransactionBoundaries(options);if(!pathExistsNoFollow(options.transactionDirectory))return null;requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);requireReadOnlyReceiptMount(options.transactionDirectory,options);requireTrustedTransactionPath(options.backupDirectory,TRANSACTION_DIRECTORY_MODE,options);requireTrustedTransactionPath(options.manifestFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.manifestFile,MAX_MANIFEST_BYTES);if(!options.readOnlyReceipt&&(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid)||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("transaction manifest ownership changed while it was read")}return parseManifest(stable.bytes.toString("utf8"))}function transactionOptionsAt(options,transactionDirectory){return{...options,transactionDirectory,backupDirectory:import_node_path2.default.join(transactionDirectory,"backups"),manifestFile:import_node_path2.default.join(transactionDirectory,"manifest.json")}}function loadCommitReceipt(options){requireTransactionBoundaries(options);if(!pathExistsNoFollow(options.commitReceiptDirectory))return null;requireTrustedTransactionPath(options.commitReceiptDirectory,TRANSACTION_DIRECTORY_MODE,options);if(pathExistsNoFollow(options.commitReceiptFile)){requireReadOnlyReceiptMount(options.commitReceiptDirectory,options);requireTrustedTransactionPath(options.commitReceiptFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.commitReceiptFile,MAX_COMMIT_RECEIPT_BYTES);if(!options.readOnlyReceipt&&(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid)||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("commit receipt ownership changed while it was read")}return{receipt:parseCommitReceipt(stable.bytes.toString("utf8")),compact:true}}const stagedOptions=transactionOptionsAt(options,options.commitReceiptDirectory);const staged=loadManifest(stagedOptions);if(!staged||staged.bootstrapIdentity===null){fail4("durable commit staging receipt is incomplete")}verifyAllBackups(staged.files,stagedOptions);return{receipt:{schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:staged.agent,profileFingerprint:staged.profileFingerprint,bootstrapIdentity:staged.bootstrapIdentity},compact:false}}function verifyBackup(receipt,options){const backupPath=import_node_path2.default.join(options.backupDirectory,receipt.backup);requireTrustedTransactionPath(backupPath,TRANSACTION_FILE_MODE,options);const stable=readStableFile(backupPath,MAX_TRANSACTION_FILE_BYTES);const digest=(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex");if(stable.bytes.length!==receipt.size||digest!==receipt.sha256){fail4(`transaction backup does not match its receipt: ${receipt.path}`)}return stable.bytes}function verifyAllBackups(receipts,options){const backups=new Map;for(const receipt of receipts){if(receipt.state==="file"){backups.set(receipt.path,verifyBackup(receipt,options))}}return backups}function fileMatchesReceipt(target,receipt){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return false;fail4(`could not inspect managed output ${target}`)}if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1)return false;const stable=readStableFile(target,MAX_TRANSACTION_FILE_BYTES);return stable.bytes.length===receipt.size&&(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex")===receipt.sha256&&Number(stable.stat.uid)===receipt.uid&&Number(stable.stat.gid)===receipt.gid&&Number(stable.stat.mode&0o7777n)===receipt.mode}function directoryMatchesReceipt(target,receipt){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return false;fail4(`could not inspect managed output directory ${target}`)}return!stat.isSymbolicLink()&&stat.isDirectory()&&stat.uid===receipt.uid&&stat.gid===receipt.gid&&modeOf2(stat)===receipt.mode}function removeTransactionDirectory(options){requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(options.transactionDirectory,{force:false,recursive:true});fsyncDirectory(options.transactionParentDirectory);if(pathExistsNoFollow(options.transactionDirectory)){fail4("transaction directory remained after cleanup")}}function assertCommitReceiptMatches(receipt,expected){if(receipt.agent!==expected.agent||expected.profileFingerprint!==void 0&&receipt.profileFingerprint!==expected.profileFingerprint||receipt.bootstrapIdentity!==expected.bootstrapIdentity){fail4("durable commit receipt belongs to a different bootstrap attempt")}}function loadCommitStagingManifest(options){if(!pathExistsNoFollow(options.manifestFile))return null;requireTrustedTransactionPath(options.manifestFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.manifestFile,MAX_MANIFEST_BYTES);if(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("durable commit staging manifest ownership changed while it was read")}return parseManifest(stable.bytes.toString("utf8"))}function retireInterruptedCommitReceiptWrites(receipt,options){const temporaryPattern=new RegExp(`^\\.${MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE.replace(".","\\.")}\\.[a-f0-9]{24}$`,"u");for(const entry of import_node_fs2.default.readdirSync(options.commitReceiptDirectory)){if(!temporaryPattern.test(entry))continue;const target=import_node_path2.default.join(options.commitReceiptDirectory,entry);const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==options.trustedUid||stat.gid!==options.trustedGid||![ATOMIC_TEMPORARY_FILE_MODE,TRANSACTION_FILE_MODE].includes(modeOf2(stat))){fail4("interrupted durable commit receipt write has unsafe metadata")}const stable=readStableFile(target,MAX_COMMIT_RECEIPT_BYTES);const mode=Number(stable.stat.mode&0o7777n);if(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid||![ATOMIC_TEMPORARY_FILE_MODE,TRANSACTION_FILE_MODE].includes(mode)){fail4("interrupted durable commit receipt write changed during verification")}if(stable.bytes.length>0){let interruptedReceipt=null;try{interruptedReceipt=parseCommitReceipt(stable.bytes.toString("utf8"))}catch{}if(interruptedReceipt)assertCommitReceiptMatches(interruptedReceipt,receipt)}import_node_fs2.default.unlinkSync(target);fsyncDirectory(options.commitReceiptDirectory)}}function compactDurableCommitReceipt(state,options){if(!state.compact){atomicWriteTrustedFile(options.commitReceiptFile,canonicalCommitReceipt(state.receipt),TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid);fsyncDirectory(options.commitReceiptDirectory)}retireInterruptedCommitReceiptWrites(state.receipt,options);const stagedOptions=transactionOptionsAt(options,options.commitReceiptDirectory);const manifestExists=pathExistsNoFollow(stagedOptions.manifestFile);const backupsExist=pathExistsNoFollow(stagedOptions.backupDirectory);const unexpectedBeforeCleanup=import_node_fs2.default.readdirSync(options.commitReceiptDirectory).filter(entry=>![MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE,import_node_path2.default.basename(stagedOptions.backupDirectory),import_node_path2.default.basename(stagedOptions.manifestFile)].includes(entry));if(unexpectedBeforeCleanup.length!==0){fail4("durable commit receipt directory contains unexpected artifacts")}if(manifestExists){const staged=loadCommitStagingManifest(stagedOptions);if(!staged||staged.bootstrapIdentity===null){fail4("durable commit staging receipt disappeared during cleanup")}assertCommitReceiptMatches(state.receipt,{agent:staged.agent,profileFingerprint:staged.profileFingerprint,bootstrapIdentity:staged.bootstrapIdentity})}if(backupsExist){requireTrustedTransactionPath(stagedOptions.backupDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(stagedOptions.backupDirectory,{force:false,recursive:true});fsyncDirectory(options.commitReceiptDirectory)}if(manifestExists){requireTrustedTransactionPath(stagedOptions.manifestFile,TRANSACTION_FILE_MODE,options);import_node_fs2.default.unlinkSync(stagedOptions.manifestFile);fsyncDirectory(options.commitReceiptDirectory)}const unexpected=import_node_fs2.default.readdirSync(options.commitReceiptDirectory).filter(entry=>entry!==MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE);if(unexpected.length!==0){fail4("durable commit receipt directory contains unexpected artifacts")}const verified=loadCommitReceipt(options);if(!verified?.compact)fail4("durable commit receipt did not compact successfully");assertCommitReceiptMatches(verified.receipt,state.receipt)}function beginManagedStartupSharedStateTransaction(profile,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot begin a transaction from a read-only rollback receipt")}requireTransactionBoundaries(options);const profileFingerprint=fingerprintManagedStartupProfile(profile);const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("a durable managed bootstrap commit receipt already exists")}assertCommitReceiptMatches(committed.receipt,{agent:profile.agent,profileFingerprint,bootstrapIdentity:options.bootstrapIdentity});fail4("this managed bootstrap attempt is already durably committed")}const pending=loadManifest(options);if(pending){if(pending.agent!==profile.agent||pending.profileFingerprint!==profileFingerprint||pending.bootstrapIdentity!==options.bootstrapIdentity){fail4("a pending managed startup transaction belongs to a different agent, profile fingerprint, or bootstrap attempt")}verifyAllBackups(pending.files,options);return false}const targets=managedOutputTargets(profile,options);if(targets.files.length>MAX_TRANSACTION_FILES){fail4("managed startup transaction has too many file targets")}const snapshots=targets.files.map((target,index)=>snapshotFile(target,index,profile.agent,options));const totalBytes=snapshots.reduce((sum,snapshot)=>sum+(snapshot.bytes?.length??0),0);if(totalBytes>MAX_TRANSACTION_TOTAL_BYTES){fail4("managed startup transaction backup exceeds the total size limit")}const directories=targets.directories.map(target=>snapshotDirectory(target,profile.agent,options));const manifest={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:profile.agent,profileFingerprint,bootstrapIdentity:options.bootstrapIdentity,files:snapshots.map(({receipt})=>receipt),directories};let createdTransactionIdentity;try{import_node_fs2.default.mkdirSync(options.transactionDirectory,{mode:TRANSACTION_DIRECTORY_MODE});const created=import_node_fs2.default.lstatSync(options.transactionDirectory,{bigint:true});if(!created.isDirectory()||created.isSymbolicLink()){fail4("new transaction path is not a directory")}createdTransactionIdentity={dev:created.dev,ino:created.ino,uid:created.uid,gid:created.gid};import_node_fs2.default.chownSync(options.transactionDirectory,options.trustedUid,options.trustedGid);import_node_fs2.default.chmodSync(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE);fsyncDirectory(options.transactionParentDirectory);import_node_fs2.default.mkdirSync(options.backupDirectory,{mode:TRANSACTION_DIRECTORY_MODE});import_node_fs2.default.chownSync(options.backupDirectory,options.trustedUid,options.trustedGid);import_node_fs2.default.chmodSync(options.backupDirectory,TRANSACTION_DIRECTORY_MODE);fsyncDirectory(options.transactionDirectory);for(const snapshot of snapshots){if(snapshot.receipt.state!=="file"||snapshot.bytes===null)continue;atomicWriteTrustedFile(import_node_path2.default.join(options.backupDirectory,snapshot.receipt.backup),snapshot.bytes,TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid)}fsyncDirectory(options.backupDirectory);atomicWriteTrustedFile(options.manifestFile,canonicalManifest(manifest),TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid);fsyncDirectory(options.transactionDirectory);loadManifest(options)}catch(error){try{if(createdTransactionIdentity&&pathExistsNoFollow(options.transactionDirectory)){const current=import_node_fs2.default.lstatSync(options.transactionDirectory,{bigint:true});if(!current.isSymbolicLink()&¤t.isDirectory()&¤t.dev===createdTransactionIdentity.dev&¤t.ino===createdTransactionIdentity.ino&¤t.uid===createdTransactionIdentity.uid&¤t.gid===createdTransactionIdentity.gid){import_node_fs2.default.chmodSync(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE);import_node_fs2.default.chownSync(options.transactionDirectory,options.trustedUid,options.trustedGid)}requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(options.transactionDirectory,{force:true,recursive:true})}}catch{}throw error}return true}function ensureOriginalDirectories(receipts,expectedAgent,options){for(const receipt of receipts){if(receipt.state!=="directory")continue;const target=absoluteTarget(receipt.path,options);validateExistingAncestors(import_node_path2.default.join(target,".restore"),expectedAgent,options);let stat=null;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code!=="ENOENT"){fail4(`could not inspect restore directory ${target}`)}}if(stat&&(stat.isSymbolicLink()||!stat.isDirectory())){fail4(`restore directory is unsafe: ${target}`)}if(stat&&directoryMatchesReceipt(target,receipt))continue;if(!stat)import_node_fs2.default.mkdirSync(target,{mode:receipt.mode});import_node_fs2.default.chownSync(target,receipt.uid,receipt.gid);import_node_fs2.default.chmodSync(target,receipt.mode)}}function restoreFiles(receipts,backups,expectedAgent,options){for(const receipt of receipts){const target=absoluteTarget(receipt.path,options);validateExistingAncestors(target,expectedAgent,options);if(receipt.state==="absent"){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")continue;fail4(`could not inspect new managed output ${target}`)}if(stat.isDirectory()){fail4(`new managed output unexpectedly became a directory: ${target}`)}import_node_fs2.default.unlinkSync(target);continue}if(fileMatchesReceipt(target,receipt))continue;const bytes=backups.get(receipt.path);if(!bytes)fail4(`verified transaction backup is missing: ${receipt.path}`);let current=null;try{current=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code!=="ENOENT"){fail4(`could not inspect managed output before restore: ${target}`)}}if(current?.isDirectory()){fail4(`managed output unexpectedly became a directory: ${target}`)}atomicWriteTrustedFile(target,bytes,receipt.mode,receipt.uid,receipt.gid)}}function restoreDirectoryMetadata(receipts,options){for(const receipt of[...receipts].reverse()){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){try{import_node_fs2.default.rmdirSync(target)}catch(error){if(error.code==="ENOENT")continue;fail4(`could not remove newly created managed directory ${target}`)}continue}if(directoryMatchesReceipt(target,receipt))continue;const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`managed directory changed type during restore: ${target}`)}import_node_fs2.default.chownSync(target,receipt.uid,receipt.gid);import_node_fs2.default.chmodSync(target,receipt.mode)}}function verifyRestoration(manifest,options){for(const receipt of manifest.files){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){if(pathExistsNoFollow(target)){fail4(`new managed output remained after rollback: ${target}`)}continue}const stable=readStableFile(target,MAX_TRANSACTION_FILE_BYTES);if(stable.bytes.length!==receipt.size||(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex")!==receipt.sha256||Number(stable.stat.uid)!==receipt.uid||Number(stable.stat.gid)!==receipt.gid||Number(stable.stat.mode&0o7777n)!==receipt.mode){fail4(`managed output was not restored exactly: ${target}`)}}for(const receipt of manifest.directories){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){if(pathExistsNoFollow(target)){fail4(`new managed directory remained after rollback: ${target}`)}continue}const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isDirectory()||stat.uid!==receipt.uid||stat.gid!==receipt.gid||modeOf2(stat)!==receipt.mode){fail4(`managed directory metadata was not restored exactly: ${target}`)}}}function rollbackManagedStartupSharedStateTransaction(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("shared state is already durably committed")}assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});fail4("shared state is already durably committed and cannot be rolled back")}const manifest=loadManifest(options);if(!manifest)return false;if(manifest.agent!==expectedAgent){fail4(`pending transaction targets ${manifest.agent}, expected ${expectedAgent}`)}if(manifest.bootstrapIdentity!==options.bootstrapIdentity){fail4("pending transaction belongs to a different bootstrap attempt")}const backups=verifyAllBackups(manifest.files,options);ensureOriginalDirectories(manifest.directories,expectedAgent,options);restoreFiles(manifest.files,backups,expectedAgent,options);restoreDirectoryMetadata(manifest.directories,options);verifyRestoration(manifest,options);if(!options.readOnlyReceipt){removeTransactionDirectory(options)}return true}function commitManagedStartupSharedStateTransaction(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot commit a read-only rollback receipt")}const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("durable commit receipt is missing its expected bootstrap identity")}assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});compactDurableCommitReceipt(committed,options);return true}const manifest=loadManifest(options);if(!manifest)return false;if(manifest.agent!==expectedAgent){fail4(`pending transaction targets ${manifest.agent}, expected ${expectedAgent}`)}if(manifest.bootstrapIdentity!==options.bootstrapIdentity){fail4("pending transaction belongs to a different bootstrap attempt")}if(manifest.bootstrapIdentity===null){removeTransactionDirectory(options);return true}verifyAllBackups(manifest.files,options);if(pathExistsNoFollow(options.commitReceiptDirectory)){fail4("durable commit receipt path appeared before transaction commit")}try{import_node_fs2.default.renameSync(options.transactionDirectory,options.commitReceiptDirectory);fsyncDirectory(options.transactionParentDirectory)}catch(error){fail4(`could not atomically establish durable commit state: ${error.message}`)}const renamed=loadCommitReceipt(options);if(!renamed)fail4("durable commit state disappeared after atomic rename");assertCommitReceiptMatches(renamed.receipt,{agent:expectedAgent,profileFingerprint:manifest.profileFingerprint,bootstrapIdentity:manifest.bootstrapIdentity});compactDurableCommitReceipt(renamed,options);return true}function clearManagedStartupSharedStateCommitReceipt(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot clear a durable commit from a read-only receipt")}if(options.bootstrapIdentity===null){fail4("durable commit cleanup requires its bootstrap identity")}const committed=loadCommitReceipt(options);if(!committed)return false;assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});compactDurableCommitReceipt(committed,options);requireTrustedTransactionPath(options.commitReceiptDirectory,TRANSACTION_DIRECTORY_MODE,options);requireTrustedTransactionPath(options.commitReceiptFile,TRANSACTION_FILE_MODE,options);const entries=import_node_fs2.default.readdirSync(options.commitReceiptDirectory);if(entries.length!==1||entries[0]!==MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE){fail4("durable commit receipt directory contains unexpected artifacts")}import_node_fs2.default.rmSync(options.commitReceiptDirectory,{force:false,recursive:true});fsyncDirectory(options.transactionParentDirectory);if(pathExistsNoFollow(options.commitReceiptDirectory)){fail4("durable commit receipt remained after cleanup")}return true}function getManagedStartupSharedStateTransactionStatus(expected,inputOptions={}){const options=resolveOptions({...inputOptions,bootstrapIdentity:expected.bootstrapIdentity});requireTransactionIdentity(options);const manifest=loadManifest(options);if(manifest){if(manifest.agent!==expected.agent||manifest.profileFingerprint!==expected.profileFingerprint||manifest.bootstrapIdentity!==expected.bootstrapIdentity){fail4("pending transaction does not match the expected agent, profile fingerprint, or bootstrap identity")}verifyAllBackups(manifest.files,options);return"pending"}const committed=loadCommitReceipt(options);if(!committed)return"none";assertCommitReceiptMatches(committed.receipt,expected);return"committed"}var MANAGED_STARTUP_PROFILE_ENV="NEMOCLAW_STARTUP_PROFILE_B64";var MANAGED_STARTUP_CA_ENV="NEMOCLAW_CORPORATE_CA_B64";var MANAGED_STARTUP_RUNTIME_ENV_FILE="/run/nemoclaw/managed-startup-runtime.env";var MANAGED_STARTUP_RUNTIME_EXECUTABLE="/usr/local/lib/nemoclaw/managed-startup-image-runtime.cjs";var MANAGED_STARTUP_MERGED_CA_FILE="/run/nemoclaw/managed-startup-ca-bundle.pem";var MANAGED_STARTUP_COMPLETION_FILE="/run/nemoclaw/managed-startup-complete.json";var MANAGED_STARTUP_CORPORATE_CA_FILE="/usr/local/share/nemoclaw/corporate-ca.pem";var MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY="/usr/local/share/ca-certificates";var MANAGED_STARTUP_SYSTEM_CA_ANCHOR_RE=/^nemoclaw-corporate-ca-[0-9]{2}\.crt$/u;var SYSTEM_CA_BUNDLE_FILE="/etc/ssl/certs/ca-certificates.crt";var UPDATE_CA_CERTIFICATES_EXECUTABLE="/usr/sbin/update-ca-certificates";var MANAGED_STARTUP_TLS_ENV_NAMES=new Set(["CURL_CA_BUNDLE","GIT_SSL_CAINFO","NODE_EXTRA_CA_CERTS","REQUESTS_CA_BUNDLE","SSL_CERT_FILE"]);var MESSAGING_RUNTIME_PLAN_FILE="/usr/local/share/nemoclaw/messaging-runtime-plan.json";var ROOT_STATE_PARENT="/var/lib/nemoclaw";var ROOT_RUNTIME_DIRECTORY="/run/nemoclaw";var ROOT_OWNED_DIRECTORY_MODE=493;var MAX_TRUST_BUNDLE_BYTES=4*1024*1024;var HERMES_MANAGED_CONFIG_FILES=["/sandbox/.hermes/config.yaml","/sandbox/.hermes/.env"];var HERMES_GENERATED_MANAGED_POLICY_FILE="/sandbox/.hermes/managed-policy.json";var HERMES_INSTALLED_MANAGED_POLICY_FILE="/usr/local/share/nemoclaw/hermes-managed-policy.json";var MAX_HERMES_MANAGED_POLICY_BYTES=4*1024*1024;var FIXED_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";var SHA256_RE4=/^[a-f0-9]{64}$/u;var MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION=1;var MAX_MANAGED_STARTUP_COMPLETION_BYTES=4096;var MAX_MANAGED_STARTUP_RUNTIME_ENVIRONMENT_BYTES=512*1024;var ManagedStartupImageActionPlanError=class extends Error{constructor(message){super(`Cannot build managed startup image action plan: ${message}`);this.name="ManagedStartupImageActionPlanError"}};var ManagedStartupImageRuntimeError=class extends Error{constructor(message){super(`Managed startup image application failed: ${message}`);this.name="ManagedStartupImageRuntimeError"}};function failActionPlan(message){throw new ManagedStartupImageActionPlanError(message)}function exactActionPlanAgent(value){if(MANAGED_STARTUP_AGENTS.includes(value)){return value}return failActionPlan(`unsupported agent ${JSON.stringify(value)}`)}function fail5(message){throw new ManagedStartupImageRuntimeError(message)}function validateManagedStartupApplicationRuntimePlan(plan){if(typeof plan!=="object"||plan===null){return fail5("application runtime plan must be an object")}const exportEnvironment=plan.exportEnvironment;const unsetEnvironment=plan.unsetEnvironment;if(typeof exportEnvironment!=="object"||exportEnvironment===null||Array.isArray(exportEnvironment)||!Array.isArray(unsetEnvironment)){return fail5("application runtime plan must contain exports and unsets")}const exports2={};for(const[name,value]of Object.entries(exportEnvironment)){if(!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){return fail5(`invalid application runtime environment key ${JSON.stringify(name)}`)}if(typeof value!=="string"||value.includes("\0")||/[\r\n]/u.test(value)){return fail5(`application runtime environment value for ${name} must be single-line text`)}exports2[name]=value}const unsets=new Set;for(const name of unsetEnvironment){if(typeof name!=="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){return fail5(`invalid application runtime unset ${JSON.stringify(name)}`)}if(unsets.has(name)){return fail5(`duplicate application runtime unset ${name}`)}if(Object.hasOwn(exports2,name)){return fail5(`application runtime cannot both export and unset ${name}`)}unsets.add(name)}return Object.freeze({exportEnvironment:Object.freeze(Object.fromEntries(Object.entries(exports2).sort(([left],[right])=>left.localeCompare(right)))),unsetEnvironment:Object.freeze([...unsets].sort())})}function applyManagedStartupCommandEnvironmentPlan(environment,plan){const validated=validateManagedStartupApplicationRuntimePlan(plan);const applied={...environment};for(const name of[...Object.keys(validated.exportEnvironment),...validated.unsetEnvironment]){delete applied[name]}return applied}function exactAgent2(value){if(MANAGED_STARTUP_AGENTS.includes(value)){return value}return fail5(`unsupported agent ${JSON.stringify(value)}`)}function managedTransactionProfile(expectedAgentInput,env=process.env){requireRoot();const expectedAgent=exactAgent2(expectedAgentInput);if(env.NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION!=="1"){fail5("shared-state transactions require a complete managed image")}const encodedProfile=env[MANAGED_STARTUP_PROFILE_ENV];if(!encodedProfile)fail5(`${MANAGED_STARTUP_PROFILE_ENV} is required`);const profile=decodeManagedStartupProfile(encodedProfile);if(profile.agent!==expectedAgent){fail5(`shared-state transaction profile targets ${profile.agent}, expected ${expectedAgent}`)}return profile}function requireRoot(){if(process.geteuid?.()!==0){fail5("managed startup requires container effective uid 0")}}function modeOf3(stat){return stat.mode&511}function requireRootOwnedDirectory(target,mode){let stat;try{stat=import_node_fs3.default.lstatSync(target)}catch{fail5(`required root-owned directory is missing: ${target}`)}if(stat.isSymbolicLink()||!stat.isDirectory()||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==mode){fail5(`${target} must be a root:root directory with mode ${mode.toString(8)}`)}}function ensureRootOwnedDirectory(target,mode=ROOT_OWNED_DIRECTORY_MODE){const parent=import_node_path3.default.dirname(target);const parentStat=import_node_fs3.default.lstatSync(parent);if(parentStat.isSymbolicLink()||!parentStat.isDirectory()||parentStat.uid!==0||parentStat.gid!==0||(modeOf3(parentStat)&18)!==0){fail5(`refusing unsafe parent directory for ${target}`)}try{import_node_fs3.default.mkdirSync(target,{mode});import_node_fs3.default.chownSync(target,0,0);import_node_fs3.default.chmodSync(target,mode)}catch(error){if(error.code!=="EEXIST"){fail5(`could not create ${target}`)}}requireRootOwnedDirectory(target,mode)}function requireSafeExistingRootTarget(target){let stat;try{stat=import_node_fs3.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return;fail5(`could not inspect ${target}`)}if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0){fail5(`refusing to replace unsafe root-owned file ${target}`)}}function atomicWriteRootFile(target,contents,mode){const parent=import_node_path3.default.dirname(target);const parentStat=import_node_fs3.default.lstatSync(parent);if(parentStat.isSymbolicLink()||!parentStat.isDirectory()||parentStat.uid!==0||parentStat.gid!==0||(modeOf3(parentStat)&18)!==0){fail5(`refusing unsafe root-owned file parent ${parent}`)}requireSafeExistingRootTarget(target);const temporary=import_node_path3.default.join(parent,`.${import_node_path3.default.basename(target)}.${(0,import_node_crypto6.randomBytes)(12).toString("hex")}`);let descriptor;try{descriptor=import_node_fs3.default.openSync(temporary,import_node_fs3.default.constants.O_CREAT|import_node_fs3.default.constants.O_EXCL|import_node_fs3.default.constants.O_WRONLY|import_node_fs3.default.constants.O_NOFOLLOW,384);import_node_fs3.default.fchownSync(descriptor,0,0);import_node_fs3.default.writeFileSync(descriptor,contents);import_node_fs3.default.fchmodSync(descriptor,mode);import_node_fs3.default.fsyncSync(descriptor);import_node_fs3.default.closeSync(descriptor);descriptor=void 0;import_node_fs3.default.renameSync(temporary,target)}catch(error){if(descriptor!==void 0)import_node_fs3.default.closeSync(descriptor);try{import_node_fs3.default.unlinkSync(temporary)}catch{}fail5(`could not atomically write ${target}: ${error.message}`)}const stat=import_node_fs3.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==mode){fail5(`root-owned output failed metadata verification: ${target}`)}}function removeSafeRootFile(target){requireSafeExistingRootTarget(target);try{import_node_fs3.default.unlinkSync(target)}catch(error){if(error.code!=="ENOENT"){fail5(`could not remove ${target}`)}}}function trustedExecutable(target){try{const stat=import_node_fs3.default.lstatSync(target);return!stat.isSymbolicLink()&&stat.isFile()&&stat.uid===0&&stat.gid===0&&(modeOf3(stat)&18)===0&&(modeOf3(stat)&73)!==0}catch{return false}}function readSandboxIdentity(){const readId=flag=>{const result=(0,import_node_child_process.spawnSync)("/usr/bin/id",[flag,"sandbox"],{encoding:"utf8",env:{PATH:FIXED_PATH}});const value=result.stdout.trim();if(result.status!==0||!/^[1-9][0-9]*$/u.test(value)){fail5("could not resolve the sandbox account")}return value};return{uid:readId("-u"),gid:readId("-g")}}function managedStartupSandboxPrefix(){if(trustedExecutable("/usr/bin/setpriv")){const identity=readSandboxIdentity();return["/usr/bin/setpriv",`--reuid=${identity.uid}`,`--regid=${identity.gid}`,"--init-groups","--"]}return fail5("a trusted setpriv executable is required")}function commandEnvironment(configurationEnvironment,applicationRuntime){const env=applyManagedStartupCommandEnvironmentPlan({...process.env,...configurationEnvironment,HOME:"/sandbox",PATH:FIXED_PATH,NPM_CONFIG_OFFLINE:"true",npm_config_offline:"true",PIP_DISABLE_PIP_VERSION_CHECK:"1",PIP_NO_INDEX:"1",UV_OFFLINE:"1"},applicationRuntime);delete env[MANAGED_STARTUP_PROFILE_ENV];delete env[MANAGED_STARTUP_CA_ENV];return env}function execute(argv,runAs,configurationEnvironment,applicationRuntime,capture=false){if(argv.length===0)fail5("refusing an empty managed startup command");const command=runAs==="sandbox"?[...managedStartupSandboxPrefix(),...argv]:[...argv];const result=(0,import_node_child_process.spawnSync)(command[0],command.slice(1),{encoding:"utf8",env:commandEnvironment(configurationEnvironment,applicationRuntime),stdio:capture?"pipe":"inherit"});if(result.error){fail5(`could not execute ${argv[0]}: ${result.error.message}`)}if(result.status!==0){const detail=capture?`: ${(result.stderr||result.stdout).trim()}`:"";fail5(`${argv[0]} exited with status ${String(result.status??"unknown")}${detail}`)}return{status:result.status,stdout:result.stdout??"",stderr:result.stderr??""}}function generatorCommand(agent){switch(agent){case"openclaw":return["/usr/local/bin/node","--experimental-strip-types","/scripts/generate-openclaw-config.mts"];case"hermes":return["/usr/local/bin/node","--experimental-strip-types","/opt/nemoclaw-hermes-config/generate-config.ts"];case"langchain-deepagents-code":return["/usr/local/bin/node","--experimental-strip-types","/opt/nemoclaw-deepagents-code/generate-config.ts"];case"pi":return["/usr/local/bin/node","--experimental-strip-types","/opt/nemoclaw-pi/generate-config.ts"]}}function messagingCommand(agent,phase,mode){return["/usr/local/bin/node","--experimental-strip-types","/src/lib/messaging/applier/build/messaging-build-applier.mts","--agent",agent,"--phase",phase,"--mode",mode,...phase==="post-agent-install"?["--managed-startup-runtime"]:[]]}function assertActionAgent(inputAgent,actionAgent){if(inputAgent!==actionAgent){failActionPlan(`action for ${actionAgent} cannot be used by ${inputAgent}`)}}function buildManagedStartupImageActionPlan(input){const inputAgent=exactActionPlanAgent(input.agent);const commands=[];let dashboardActions=0;let generateActions=0;let runtimeMessagingActions=0;let postMessagingActions=0;for(const action of input.actions){switch(action.kind){case"configure-dashboard":{if(action.dashboard.agent!==input.agent){failActionPlan(`dashboard for ${action.dashboard.agent} cannot be used by ${input.agent}`)}dashboardActions+=1;break}case"generate-agent-config":{assertActionAgent(inputAgent,exactActionPlanAgent(action.agent));if(action.runAs!=="sandbox"){failActionPlan("agent configuration generation must run as sandbox")}generateActions+=1;commands.push({action:"generate-agent-config",runAs:action.runAs,argv:generatorCommand(action.agent)});break}case"apply-messaging-plan":{assertActionAgent(inputAgent,exactActionPlanAgent(action.agent));if(action.mode!=="apply"&&action.mode!=="clear"){failActionPlan("messaging intent must be apply or clear")}if(action.phase==="runtime-setup"){if(action.runAs!=="root"){failActionPlan("messaging runtime setup must run as root")}runtimeMessagingActions+=1;commands.push({action:"messaging-runtime-setup",runAs:action.runAs,argv:messagingCommand(action.agent,action.phase,action.mode)})}else if(action.phase==="post-agent-install"){if(action.runAs!=="sandbox"){failActionPlan("messaging post-agent configuration must run as sandbox")}postMessagingActions+=1;commands.push({action:"messaging-post-agent-install",runAs:action.runAs,argv:messagingCommand(action.agent,action.phase,action.mode)})}else{failActionPlan("unsupported messaging construction phase")}break}default:failActionPlan("unsupported managed startup construction action")}}if(dashboardActions!==1){failActionPlan("exactly one dashboard construction action is required")}if(generateActions!==1){failActionPlan("exactly one agent config construction action is required")}const supportsMessaging=MANAGED_STARTUP_MESSAGING_AGENTS.includes(inputAgent);const expectedMessagingActions=supportsMessaging?1:0;if(runtimeMessagingActions!==expectedMessagingActions||postMessagingActions!==expectedMessagingActions){failActionPlan(`${inputAgent} requires ${String(expectedMessagingActions)} action for each messaging phase`)}const expectedOrder=supportsMessaging?["messaging-runtime-setup","generate-agent-config","messaging-post-agent-install"]:["generate-agent-config"];if(commands.some((command,index)=>command.action!==expectedOrder[index])){failActionPlan(`${inputAgent} image actions are not in the required construction order`)}return Object.freeze(commands.map(command=>Object.freeze({...command,argv:Object.freeze([...command.argv])})))}function prepareMessagingRuntimeTarget(mode){if(mode==="clear"){removeSafeRootFile(MESSAGING_RUNTIME_PLAN_FILE);return}requireSafeExistingRootTarget(MESSAGING_RUNTIME_PLAN_FILE);try{import_node_fs3.default.unlinkSync(MESSAGING_RUNTIME_PLAN_FILE)}catch(error){if(error.code!=="ENOENT"){fail5("could not prepare the messaging runtime-plan target")}}}function verifyMessagingRuntimeTarget(mode){if(mode==="clear"){if(import_node_fs3.default.existsSync(MESSAGING_RUNTIME_PLAN_FILE)){fail5("clear messaging profile left a runtime-plan artifact")}return}const stat=import_node_fs3.default.lstatSync(MESSAGING_RUNTIME_PLAN_FILE);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==420){fail5("messaging runtime-plan artifact failed root ownership validation")}}function runInternalSandboxAction(action,configurationEnvironment,applicationRuntime,extraEnvironment={}){execute(["/usr/local/bin/node",MANAGED_STARTUP_RUNTIME_EXECUTABLE,`--internal-${action}`],"sandbox",{...configurationEnvironment,...extraEnvironment},applicationRuntime)}function sealOpenClawConfiguration(configurationEnvironment,applicationRuntime){const validation=execute(["/usr/local/bin/openclaw","config","validate","--json"],"sandbox",{...configurationEnvironment,OPENCLAW_CONFIG_PATH:"/sandbox/.openclaw/openclaw.json"},applicationRuntime,true);let parsed;try{parsed=JSON.parse(validation.stdout)}catch{fail5("OpenClaw config validation did not emit JSON")}if(typeof parsed!=="object"||parsed===null||parsed.valid!==true){fail5("OpenClaw rejected the generated managed startup config")}runInternalSandboxAction("write-openclaw-hash",configurationEnvironment,applicationRuntime)}function sameStableFileMetadata(left,right){return left.dev===right.dev&&left.ino===right.ino&&left.mode===right.mode&&left.nlink===right.nlink&&left.uid===right.uid&&left.gid===right.gid&&left.size===right.size&&left.mtimeNs===right.mtimeNs&&left.ctimeNs===right.ctimeNs}function readStableRegularFileSnapshot(target,maxBytes){if(typeof import_node_fs3.default.constants.O_NOFOLLOW!=="number"){fail5("O_NOFOLLOW is unavailable for managed startup file reads")}const nonblock=typeof import_node_fs3.default.constants.O_NONBLOCK==="number"?import_node_fs3.default.constants.O_NONBLOCK:0;let descriptor;try{descriptor=import_node_fs3.default.openSync(target,import_node_fs3.default.constants.O_RDONLY|import_node_fs3.default.constants.O_NOFOLLOW|nonblock)}catch(error){if(error.code==="ENOENT")throw error;fail5(`refusing unsafe or unreadable file ${target}`)}try{const before=import_node_fs3.default.fstatSync(descriptor,{bigint:true});if(!before.isFile()||before.nlink!==1n||before.size<1n||before.size>BigInt(maxBytes)){fail5(`refusing unsafe or oversized file ${target}`)}const bytes=Buffer.alloc(Number(before.size));let offset=0;while(offset`${block.trim()} +`}function requireExactKeys(record,keys){if(Object.keys(record).sort().join(",")!==[...keys].sort().join(",")){fail4("transaction manifest contains unexpected fields")}}function parseCommitReceipt(text){let parsed;try{parsed=JSON.parse(text)}catch{fail4("commit receipt is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail4("commit receipt must be an object")}const record=parsed;requireExactKeys(record,["agent","bootstrapIdentity","profileFingerprint","schemaVersion"]);if(record.schemaVersion!==TRANSACTION_SCHEMA_VERSION||!MANAGED_STARTUP_AGENTS.includes(String(record.agent))||typeof record.profileFingerprint!=="string"||!/^[a-f0-9]{64}$/u.test(record.profileFingerprint)||typeof record.bootstrapIdentity!=="string"||!/^[a-f0-9]{64}$/u.test(record.bootstrapIdentity)){fail4("commit receipt has an invalid envelope")}const receipt={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:record.agent,profileFingerprint:record.profileFingerprint,bootstrapIdentity:record.bootstrapIdentity};if(canonicalCommitReceipt(receipt)!==text){fail4("commit receipt is not canonical")}return receipt}function safeMetadata(value){return Number.isSafeInteger(value)&&value>=0}function parseManifest(text){let parsed;try{parsed=JSON.parse(text)}catch{fail4("transaction manifest is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail4("transaction manifest must be an object")}const record=parsed;const hasBootstrapIdentity=Object.hasOwn(record,"bootstrapIdentity");requireExactKeys(record,hasBootstrapIdentity?["agent","bootstrapIdentity","directories","files","profileFingerprint","schemaVersion"]:["agent","directories","files","profileFingerprint","schemaVersion"]);const bootstrapIdentity=hasBootstrapIdentity?record.bootstrapIdentity:null;if(record.schemaVersion!==TRANSACTION_SCHEMA_VERSION||!MANAGED_STARTUP_AGENTS.includes(String(record.agent))||typeof record.profileFingerprint!=="string"||!/^[a-f0-9]{64}$/u.test(record.profileFingerprint)||!(bootstrapIdentity===null||typeof bootstrapIdentity==="string"&&/^[a-f0-9]{64}$/u.test(bootstrapIdentity))||!Array.isArray(record.files)||!Array.isArray(record.directories)||record.files.length>MAX_TRANSACTION_FILES||record.directories.length>MAX_TRANSACTION_FILES*4){fail4("transaction manifest has an invalid envelope")}const files=record.files.map(value=>{if(typeof value!=="object"||value===null||Array.isArray(value)){return fail4("transaction file receipt must be an object")}const receipt=value;if(typeof receipt.path!=="string"){return fail4("transaction file receipt path must be a string")}const receiptPath=safeRelativePath(receipt.path);if(receipt.state==="absent"){requireExactKeys(receipt,["path","state"]);return{path:receiptPath,state:"absent"}}requireExactKeys(receipt,["backup","gid","mode","path","sha256","size","state","uid"]);if(receipt.state!=="file"||typeof receipt.backup!=="string"||!/^[0-9]{3}\.bin$/u.test(receipt.backup)||typeof receipt.sha256!=="string"||!/^[a-f0-9]{64}$/u.test(receipt.sha256)||!safeMetadata(receipt.size)||receipt.size>MAX_TRANSACTION_FILE_BYTES||!safeMetadata(receipt.uid)||!safeMetadata(receipt.gid)||!safeMetadata(receipt.mode)||receipt.mode>4095){return fail4("transaction file receipt is invalid")}return{path:receiptPath,state:"file",backup:receipt.backup,sha256:receipt.sha256,size:receipt.size,uid:receipt.uid,gid:receipt.gid,mode:receipt.mode}});const directories=record.directories.map(value=>{if(typeof value!=="object"||value===null||Array.isArray(value)){return fail4("transaction directory receipt must be an object")}const receipt=value;if(typeof receipt.path!=="string"){return fail4("transaction directory receipt path must be a string")}const receiptPath=safeRelativePath(receipt.path);if(receipt.state==="absent"){requireExactKeys(receipt,["path","state"]);return{path:receiptPath,state:"absent"}}requireExactKeys(receipt,["gid","mode","path","state","uid"]);if(receipt.state!=="directory"||!safeMetadata(receipt.uid)||!safeMetadata(receipt.gid)||!safeMetadata(receipt.mode)||receipt.mode>4095){return fail4("transaction directory receipt is invalid")}return{path:receiptPath,state:"directory",uid:receipt.uid,gid:receipt.gid,mode:receipt.mode}});const filePaths=files.map(receipt=>receipt.path);const directoryPaths=directories.map(receipt=>receipt.path);const backupNames=files.filter(receipt=>receipt.state==="file").map(receipt=>receipt.backup);if(new Set(filePaths).size!==filePaths.length||new Set(directoryPaths).size!==directoryPaths.length||new Set(backupNames).size!==backupNames.length){fail4("transaction manifest contains duplicate receipts")}const manifest={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:record.agent,profileFingerprint:record.profileFingerprint,bootstrapIdentity,files,directories};const canonical=hasBootstrapIdentity?canonicalManifest(manifest):canonicalLegacyManifest(manifest);if(canonical!==text){fail4("transaction manifest is not canonical")}return manifest}function requireTrustedTransactionPath(target,mode,options){const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||(mode===TRANSACTION_DIRECTORY_MODE?!stat.isDirectory():!stat.isFile())||!options.readOnlyReceipt&&(stat.uid!==options.trustedUid||stat.gid!==options.trustedGid)||modeOf2(stat)!==mode){fail4(`transaction artifact has unsafe metadata: ${target}`)}}function requireReadOnlyReceiptMount(target,options){if(!options.readOnlyReceipt)return;const probe=import_node_path2.default.join(target,".nemoclaw-write-probe");let descriptor;try{descriptor=import_node_fs2.default.openSync(probe,import_node_fs2.default.constants.O_CREAT|import_node_fs2.default.constants.O_EXCL|import_node_fs2.default.constants.O_WRONLY|import_node_fs2.default.constants.O_NOFOLLOW,384);import_node_fs2.default.closeSync(descriptor);descriptor=void 0;import_node_fs2.default.unlinkSync(probe)}catch(error){if(descriptor!==void 0)import_node_fs2.default.closeSync(descriptor);if(error.code==="EROFS")return;fail4("copied receipt must be mounted on a read-only filesystem")}fail4("copied receipt mount is writable")}function loadManifest(options){requireTransactionBoundaries(options);if(!pathExistsNoFollow(options.transactionDirectory))return null;requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);requireReadOnlyReceiptMount(options.transactionDirectory,options);requireTrustedTransactionPath(options.backupDirectory,TRANSACTION_DIRECTORY_MODE,options);requireTrustedTransactionPath(options.manifestFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.manifestFile,MAX_MANIFEST_BYTES);if(!options.readOnlyReceipt&&(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid)||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("transaction manifest ownership changed while it was read")}return parseManifest(stable.bytes.toString("utf8"))}function transactionOptionsAt(options,transactionDirectory){return{...options,transactionDirectory,backupDirectory:import_node_path2.default.join(transactionDirectory,"backups"),manifestFile:import_node_path2.default.join(transactionDirectory,"manifest.json")}}function loadCommitReceipt(options){requireTransactionBoundaries(options);if(!pathExistsNoFollow(options.commitReceiptDirectory))return null;requireTrustedTransactionPath(options.commitReceiptDirectory,TRANSACTION_DIRECTORY_MODE,options);if(pathExistsNoFollow(options.commitReceiptFile)){requireReadOnlyReceiptMount(options.commitReceiptDirectory,options);requireTrustedTransactionPath(options.commitReceiptFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.commitReceiptFile,MAX_COMMIT_RECEIPT_BYTES);if(!options.readOnlyReceipt&&(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid)||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("commit receipt ownership changed while it was read")}return{receipt:parseCommitReceipt(stable.bytes.toString("utf8")),compact:true}}const stagedOptions=transactionOptionsAt(options,options.commitReceiptDirectory);const staged=loadManifest(stagedOptions);if(!staged||staged.bootstrapIdentity===null){fail4("durable commit staging receipt is incomplete")}verifyAllBackups(staged.files,stagedOptions);return{receipt:{schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:staged.agent,profileFingerprint:staged.profileFingerprint,bootstrapIdentity:staged.bootstrapIdentity},compact:false}}function verifyBackup(receipt,options){const backupPath=import_node_path2.default.join(options.backupDirectory,receipt.backup);requireTrustedTransactionPath(backupPath,TRANSACTION_FILE_MODE,options);const stable=readStableFile(backupPath,MAX_TRANSACTION_FILE_BYTES);const digest=(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex");if(stable.bytes.length!==receipt.size||digest!==receipt.sha256){fail4(`transaction backup does not match its receipt: ${receipt.path}`)}return stable.bytes}function verifyAllBackups(receipts,options){const backups=new Map;for(const receipt of receipts){if(receipt.state==="file"){backups.set(receipt.path,verifyBackup(receipt,options))}}return backups}function fileMatchesReceipt(target,receipt){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return false;fail4(`could not inspect managed output ${target}`)}if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1)return false;const stable=readStableFile(target,MAX_TRANSACTION_FILE_BYTES);return stable.bytes.length===receipt.size&&(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex")===receipt.sha256&&Number(stable.stat.uid)===receipt.uid&&Number(stable.stat.gid)===receipt.gid&&Number(stable.stat.mode&0o7777n)===receipt.mode}function directoryMatchesReceipt(target,receipt){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return false;fail4(`could not inspect managed output directory ${target}`)}return!stat.isSymbolicLink()&&stat.isDirectory()&&stat.uid===receipt.uid&&stat.gid===receipt.gid&&modeOf2(stat)===receipt.mode}function removeTransactionDirectory(options){requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(options.transactionDirectory,{force:false,recursive:true});fsyncDirectory(options.transactionParentDirectory);if(pathExistsNoFollow(options.transactionDirectory)){fail4("transaction directory remained after cleanup")}}function assertCommitReceiptMatches(receipt,expected){if(receipt.agent!==expected.agent||expected.profileFingerprint!==void 0&&receipt.profileFingerprint!==expected.profileFingerprint||receipt.bootstrapIdentity!==expected.bootstrapIdentity){fail4("durable commit receipt belongs to a different bootstrap attempt")}}function loadCommitStagingManifest(options){if(!pathExistsNoFollow(options.manifestFile))return null;requireTrustedTransactionPath(options.manifestFile,TRANSACTION_FILE_MODE,options);const stable=readStableFile(options.manifestFile,MAX_MANIFEST_BYTES);if(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid||Number(stable.stat.mode&0o7777n)!==TRANSACTION_FILE_MODE){fail4("durable commit staging manifest ownership changed while it was read")}return parseManifest(stable.bytes.toString("utf8"))}function retireInterruptedCommitReceiptWrites(receipt,options){const temporaryPattern=new RegExp(`^\\.${MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE.replace(".","\\.")}\\.[a-f0-9]{24}$`,"u");for(const entry of import_node_fs2.default.readdirSync(options.commitReceiptDirectory)){if(!temporaryPattern.test(entry))continue;const target=import_node_path2.default.join(options.commitReceiptDirectory,entry);const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==options.trustedUid||stat.gid!==options.trustedGid||![ATOMIC_TEMPORARY_FILE_MODE,TRANSACTION_FILE_MODE].includes(modeOf2(stat))){fail4("interrupted durable commit receipt write has unsafe metadata")}const stable=readStableFile(target,MAX_COMMIT_RECEIPT_BYTES);const mode=Number(stable.stat.mode&0o7777n);if(Number(stable.stat.uid)!==options.trustedUid||Number(stable.stat.gid)!==options.trustedGid||![ATOMIC_TEMPORARY_FILE_MODE,TRANSACTION_FILE_MODE].includes(mode)){fail4("interrupted durable commit receipt write changed during verification")}if(stable.bytes.length>0){let interruptedReceipt=null;try{interruptedReceipt=parseCommitReceipt(stable.bytes.toString("utf8"))}catch{}if(interruptedReceipt)assertCommitReceiptMatches(interruptedReceipt,receipt)}import_node_fs2.default.unlinkSync(target);fsyncDirectory(options.commitReceiptDirectory)}}function compactDurableCommitReceipt(state,options){if(!state.compact){atomicWriteTrustedFile(options.commitReceiptFile,canonicalCommitReceipt(state.receipt),TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid);fsyncDirectory(options.commitReceiptDirectory)}retireInterruptedCommitReceiptWrites(state.receipt,options);const stagedOptions=transactionOptionsAt(options,options.commitReceiptDirectory);const manifestExists=pathExistsNoFollow(stagedOptions.manifestFile);const backupsExist=pathExistsNoFollow(stagedOptions.backupDirectory);const unexpectedBeforeCleanup=import_node_fs2.default.readdirSync(options.commitReceiptDirectory).filter(entry=>![MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE,import_node_path2.default.basename(stagedOptions.backupDirectory),import_node_path2.default.basename(stagedOptions.manifestFile)].includes(entry));if(unexpectedBeforeCleanup.length!==0){fail4("durable commit receipt directory contains unexpected artifacts")}if(manifestExists){const staged=loadCommitStagingManifest(stagedOptions);if(!staged||staged.bootstrapIdentity===null){fail4("durable commit staging receipt disappeared during cleanup")}assertCommitReceiptMatches(state.receipt,{agent:staged.agent,profileFingerprint:staged.profileFingerprint,bootstrapIdentity:staged.bootstrapIdentity})}if(backupsExist){requireTrustedTransactionPath(stagedOptions.backupDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(stagedOptions.backupDirectory,{force:false,recursive:true});fsyncDirectory(options.commitReceiptDirectory)}if(manifestExists){requireTrustedTransactionPath(stagedOptions.manifestFile,TRANSACTION_FILE_MODE,options);import_node_fs2.default.unlinkSync(stagedOptions.manifestFile);fsyncDirectory(options.commitReceiptDirectory)}const unexpected=import_node_fs2.default.readdirSync(options.commitReceiptDirectory).filter(entry=>entry!==MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE);if(unexpected.length!==0){fail4("durable commit receipt directory contains unexpected artifacts")}const verified=loadCommitReceipt(options);if(!verified?.compact)fail4("durable commit receipt did not compact successfully");assertCommitReceiptMatches(verified.receipt,state.receipt)}function beginManagedStartupSharedStateTransaction(profile,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot begin a transaction from a read-only rollback receipt")}requireTransactionBoundaries(options);const profileFingerprint=fingerprintManagedStartupProfile(profile);const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("a durable managed bootstrap commit receipt already exists")}assertCommitReceiptMatches(committed.receipt,{agent:profile.agent,profileFingerprint,bootstrapIdentity:options.bootstrapIdentity});fail4("this managed bootstrap attempt is already durably committed")}const pending=loadManifest(options);if(pending){if(pending.agent!==profile.agent||pending.profileFingerprint!==profileFingerprint||pending.bootstrapIdentity!==options.bootstrapIdentity){fail4("a pending managed startup transaction belongs to a different agent, profile fingerprint, or bootstrap attempt")}verifyAllBackups(pending.files,options);return false}const targets=managedOutputTargets(profile,options);if(targets.files.length>MAX_TRANSACTION_FILES){fail4("managed startup transaction has too many file targets")}const snapshots=targets.files.map((target,index)=>snapshotFile(target,index,profile.agent,options));const totalBytes=snapshots.reduce((sum,snapshot)=>sum+(snapshot.bytes?.length??0),0);if(totalBytes>MAX_TRANSACTION_TOTAL_BYTES){fail4("managed startup transaction backup exceeds the total size limit")}const directories=targets.directories.map(target=>snapshotDirectory(target,profile.agent,options));const manifest={schemaVersion:TRANSACTION_SCHEMA_VERSION,agent:profile.agent,profileFingerprint,bootstrapIdentity:options.bootstrapIdentity,files:snapshots.map(({receipt})=>receipt),directories};let createdTransactionIdentity;try{import_node_fs2.default.mkdirSync(options.transactionDirectory,{mode:TRANSACTION_DIRECTORY_MODE});const created=import_node_fs2.default.lstatSync(options.transactionDirectory,{bigint:true});if(!created.isDirectory()||created.isSymbolicLink()){fail4("new transaction path is not a directory")}createdTransactionIdentity={dev:created.dev,ino:created.ino,uid:created.uid,gid:created.gid};import_node_fs2.default.chownSync(options.transactionDirectory,options.trustedUid,options.trustedGid);import_node_fs2.default.chmodSync(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE);fsyncDirectory(options.transactionParentDirectory);import_node_fs2.default.mkdirSync(options.backupDirectory,{mode:TRANSACTION_DIRECTORY_MODE});import_node_fs2.default.chownSync(options.backupDirectory,options.trustedUid,options.trustedGid);import_node_fs2.default.chmodSync(options.backupDirectory,TRANSACTION_DIRECTORY_MODE);fsyncDirectory(options.transactionDirectory);for(const snapshot of snapshots){if(snapshot.receipt.state!=="file"||snapshot.bytes===null)continue;atomicWriteTrustedFile(import_node_path2.default.join(options.backupDirectory,snapshot.receipt.backup),snapshot.bytes,TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid)}fsyncDirectory(options.backupDirectory);atomicWriteTrustedFile(options.manifestFile,canonicalManifest(manifest),TRANSACTION_FILE_MODE,options.trustedUid,options.trustedGid);fsyncDirectory(options.transactionDirectory);loadManifest(options)}catch(error){try{if(createdTransactionIdentity&&pathExistsNoFollow(options.transactionDirectory)){const current=import_node_fs2.default.lstatSync(options.transactionDirectory,{bigint:true});if(!current.isSymbolicLink()&¤t.isDirectory()&¤t.dev===createdTransactionIdentity.dev&¤t.ino===createdTransactionIdentity.ino&¤t.uid===createdTransactionIdentity.uid&¤t.gid===createdTransactionIdentity.gid){import_node_fs2.default.chmodSync(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE);import_node_fs2.default.chownSync(options.transactionDirectory,options.trustedUid,options.trustedGid)}requireTrustedTransactionPath(options.transactionDirectory,TRANSACTION_DIRECTORY_MODE,options);import_node_fs2.default.rmSync(options.transactionDirectory,{force:true,recursive:true})}}catch{}throw error}return true}function ensureOriginalDirectories(receipts,expectedAgent,options){for(const receipt of receipts){if(receipt.state!=="directory")continue;const target=absoluteTarget(receipt.path,options);validateExistingAncestors(import_node_path2.default.join(target,".restore"),expectedAgent,options);let stat=null;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code!=="ENOENT"){fail4(`could not inspect restore directory ${target}`)}}if(stat&&(stat.isSymbolicLink()||!stat.isDirectory())){fail4(`restore directory is unsafe: ${target}`)}if(stat&&directoryMatchesReceipt(target,receipt))continue;if(!stat)import_node_fs2.default.mkdirSync(target,{mode:receipt.mode});import_node_fs2.default.chownSync(target,receipt.uid,receipt.gid);import_node_fs2.default.chmodSync(target,receipt.mode)}}function restoreFiles(receipts,backups,expectedAgent,options){for(const receipt of receipts){const target=absoluteTarget(receipt.path,options);validateExistingAncestors(target,expectedAgent,options);if(receipt.state==="absent"){let stat;try{stat=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")continue;fail4(`could not inspect new managed output ${target}`)}if(stat.isDirectory()){fail4(`new managed output unexpectedly became a directory: ${target}`)}import_node_fs2.default.unlinkSync(target);continue}if(fileMatchesReceipt(target,receipt))continue;const bytes=backups.get(receipt.path);if(!bytes)fail4(`verified transaction backup is missing: ${receipt.path}`);let current=null;try{current=import_node_fs2.default.lstatSync(target)}catch(error){if(error.code!=="ENOENT"){fail4(`could not inspect managed output before restore: ${target}`)}}if(current?.isDirectory()){fail4(`managed output unexpectedly became a directory: ${target}`)}atomicWriteTrustedFile(target,bytes,receipt.mode,receipt.uid,receipt.gid)}}function restoreDirectoryMetadata(receipts,options){for(const receipt of[...receipts].reverse()){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){try{import_node_fs2.default.rmdirSync(target)}catch(error){if(error.code==="ENOENT")continue;fail4(`could not remove newly created managed directory ${target}`)}continue}if(directoryMatchesReceipt(target,receipt))continue;const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isDirectory()){fail4(`managed directory changed type during restore: ${target}`)}import_node_fs2.default.chownSync(target,receipt.uid,receipt.gid);import_node_fs2.default.chmodSync(target,receipt.mode)}}function verifyRestoration(manifest,options){for(const receipt of manifest.files){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){if(pathExistsNoFollow(target)){fail4(`new managed output remained after rollback: ${target}`)}continue}const stable=readStableFile(target,MAX_TRANSACTION_FILE_BYTES);if(stable.bytes.length!==receipt.size||(0,import_node_crypto5.createHash)("sha256").update(stable.bytes).digest("hex")!==receipt.sha256||Number(stable.stat.uid)!==receipt.uid||Number(stable.stat.gid)!==receipt.gid||Number(stable.stat.mode&0o7777n)!==receipt.mode){fail4(`managed output was not restored exactly: ${target}`)}}for(const receipt of manifest.directories){const target=absoluteTarget(receipt.path,options);if(receipt.state==="absent"){if(pathExistsNoFollow(target)){fail4(`new managed directory remained after rollback: ${target}`)}continue}const stat=import_node_fs2.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isDirectory()||stat.uid!==receipt.uid||stat.gid!==receipt.gid||modeOf2(stat)!==receipt.mode){fail4(`managed directory metadata was not restored exactly: ${target}`)}}}function rollbackManagedStartupSharedStateTransaction(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("shared state is already durably committed")}assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});fail4("shared state is already durably committed and cannot be rolled back")}const manifest=loadManifest(options);if(!manifest)return false;if(manifest.agent!==expectedAgent){fail4(`pending transaction targets ${manifest.agent}, expected ${expectedAgent}`)}if(manifest.bootstrapIdentity!==options.bootstrapIdentity){fail4("pending transaction belongs to a different bootstrap attempt")}const backups=verifyAllBackups(manifest.files,options);ensureOriginalDirectories(manifest.directories,expectedAgent,options);restoreFiles(manifest.files,backups,expectedAgent,options);restoreDirectoryMetadata(manifest.directories,options);verifyRestoration(manifest,options);if(!options.readOnlyReceipt){removeTransactionDirectory(options)}return true}function commitManagedStartupSharedStateTransaction(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot commit a read-only rollback receipt")}const committed=loadCommitReceipt(options);if(committed){if(options.bootstrapIdentity===null){fail4("durable commit receipt is missing its expected bootstrap identity")}assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});compactDurableCommitReceipt(committed,options);return true}const manifest=loadManifest(options);if(!manifest)return false;if(manifest.agent!==expectedAgent){fail4(`pending transaction targets ${manifest.agent}, expected ${expectedAgent}`)}if(manifest.bootstrapIdentity!==options.bootstrapIdentity){fail4("pending transaction belongs to a different bootstrap attempt")}if(manifest.bootstrapIdentity===null){removeTransactionDirectory(options);return true}verifyAllBackups(manifest.files,options);if(pathExistsNoFollow(options.commitReceiptDirectory)){fail4("durable commit receipt path appeared before transaction commit")}try{import_node_fs2.default.renameSync(options.transactionDirectory,options.commitReceiptDirectory);fsyncDirectory(options.transactionParentDirectory)}catch(error){fail4(`could not atomically establish durable commit state: ${error.message}`)}const renamed=loadCommitReceipt(options);if(!renamed)fail4("durable commit state disappeared after atomic rename");assertCommitReceiptMatches(renamed.receipt,{agent:expectedAgent,profileFingerprint:manifest.profileFingerprint,bootstrapIdentity:manifest.bootstrapIdentity});compactDurableCommitReceipt(renamed,options);return true}function clearManagedStartupSharedStateCommitReceipt(expectedAgent,inputOptions={}){const options=resolveOptions(inputOptions);requireTransactionIdentity(options);if(options.readOnlyReceipt){fail4("cannot clear a durable commit from a read-only receipt")}if(options.bootstrapIdentity===null){fail4("durable commit cleanup requires its bootstrap identity")}const committed=loadCommitReceipt(options);if(!committed)return false;assertCommitReceiptMatches(committed.receipt,{agent:expectedAgent,bootstrapIdentity:options.bootstrapIdentity});compactDurableCommitReceipt(committed,options);requireTrustedTransactionPath(options.commitReceiptDirectory,TRANSACTION_DIRECTORY_MODE,options);requireTrustedTransactionPath(options.commitReceiptFile,TRANSACTION_FILE_MODE,options);const entries=import_node_fs2.default.readdirSync(options.commitReceiptDirectory);if(entries.length!==1||entries[0]!==MANAGED_STARTUP_SHARED_COMMIT_RECEIPT_FILE){fail4("durable commit receipt directory contains unexpected artifacts")}import_node_fs2.default.rmSync(options.commitReceiptDirectory,{force:false,recursive:true});fsyncDirectory(options.transactionParentDirectory);if(pathExistsNoFollow(options.commitReceiptDirectory)){fail4("durable commit receipt remained after cleanup")}return true}function getManagedStartupSharedStateTransactionStatus(expected,inputOptions={}){const options=resolveOptions({...inputOptions,bootstrapIdentity:expected.bootstrapIdentity});requireTransactionIdentity(options);const manifest=loadManifest(options);if(manifest){if(manifest.agent!==expected.agent||manifest.profileFingerprint!==expected.profileFingerprint||manifest.bootstrapIdentity!==expected.bootstrapIdentity){fail4("pending transaction does not match the expected agent, profile fingerprint, or bootstrap identity")}verifyAllBackups(manifest.files,options);return"pending"}const committed=loadCommitReceipt(options);if(!committed)return"none";assertCommitReceiptMatches(committed.receipt,expected);return"committed"}var MANAGED_STARTUP_PROFILE_ENV="NEMOCLAW_STARTUP_PROFILE_B64";var MANAGED_STARTUP_CA_ENV="NEMOCLAW_CORPORATE_CA_B64";var MANAGED_STARTUP_RUNTIME_ENV_FILE="/run/nemoclaw/managed-startup-runtime.env";var MANAGED_STARTUP_RUNTIME_EXECUTABLE="/usr/local/lib/nemoclaw/managed-startup-image-runtime.cjs";var MANAGED_STARTUP_MERGED_CA_FILE="/run/nemoclaw/managed-startup-ca-bundle.pem";var MANAGED_STARTUP_COMPLETION_FILE="/run/nemoclaw/managed-startup-complete.json";var MANAGED_STARTUP_CORPORATE_CA_FILE="/usr/local/share/nemoclaw/corporate-ca.pem";var MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY="/usr/local/share/ca-certificates";var MANAGED_STARTUP_SYSTEM_CA_ANCHOR_RE=/^nemoclaw-corporate-ca-[0-9]{2}\.crt$/u;var SYSTEM_CA_BUNDLE_FILE="/etc/ssl/certs/ca-certificates.crt";var UPDATE_CA_CERTIFICATES_EXECUTABLE="/usr/sbin/update-ca-certificates";var MANAGED_STARTUP_TLS_ENV_NAMES=new Set(["CURL_CA_BUNDLE","GIT_SSL_CAINFO","NODE_EXTRA_CA_CERTS","REQUESTS_CA_BUNDLE","SSL_CERT_FILE"]);var MESSAGING_RUNTIME_PLAN_FILE="/usr/local/share/nemoclaw/messaging-runtime-plan.json";var ROOT_STATE_PARENT="/var/lib/nemoclaw";var ROOT_RUNTIME_DIRECTORY="/run/nemoclaw";var ROOT_OWNED_DIRECTORY_MODE=493;var MAX_TRUST_BUNDLE_BYTES=4*1024*1024;var HERMES_MANAGED_CONFIG_FILES=["/sandbox/.hermes/config.yaml","/sandbox/.hermes/.env"];var HERMES_GENERATED_MANAGED_POLICY_FILE="/sandbox/.hermes/managed-policy.json";var HERMES_INSTALLED_MANAGED_POLICY_FILE="/usr/local/share/nemoclaw/hermes-managed-policy.json";var MAX_HERMES_MANAGED_POLICY_BYTES=4*1024*1024;var FIXED_PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";var SHA256_RE4=/^[a-f0-9]{64}$/u;var MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION=1;var MAX_MANAGED_STARTUP_COMPLETION_BYTES=4096;var MAX_MANAGED_STARTUP_RUNTIME_ENVIRONMENT_BYTES=512*1024;var ManagedStartupImageActionPlanError=class extends Error{constructor(message){super(`Cannot build managed startup image action plan: ${message}`);this.name="ManagedStartupImageActionPlanError"}};var ManagedStartupImageRuntimeError=class extends Error{constructor(message){super(`Managed startup image application failed: ${message}`);this.name="ManagedStartupImageRuntimeError"}};function failActionPlan(message){throw new ManagedStartupImageActionPlanError(message)}function exactActionPlanAgent(value){if(MANAGED_STARTUP_AGENTS.includes(value)){return value}return failActionPlan(`unsupported agent ${JSON.stringify(value)}`)}function fail5(message){throw new ManagedStartupImageRuntimeError(message)}function validateManagedStartupApplicationRuntimePlan(plan){if(typeof plan!=="object"||plan===null){return fail5("application runtime plan must be an object")}const exportEnvironment=plan.exportEnvironment;const unsetEnvironment=plan.unsetEnvironment;if(typeof exportEnvironment!=="object"||exportEnvironment===null||Array.isArray(exportEnvironment)||!Array.isArray(unsetEnvironment)){return fail5("application runtime plan must contain exports and unsets")}const exports2={};for(const[name,value]of Object.entries(exportEnvironment)){if(!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){return fail5(`invalid application runtime environment key ${JSON.stringify(name)}`)}if(typeof value!=="string"||value.includes("\0")||/[\r\n]/u.test(value)){return fail5(`application runtime environment value for ${name} must be single-line text`)}exports2[name]=value}const unsets=new Set;for(const name of unsetEnvironment){if(typeof name!=="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){return fail5(`invalid application runtime unset ${JSON.stringify(name)}`)}if(unsets.has(name)){return fail5(`duplicate application runtime unset ${name}`)}if(Object.hasOwn(exports2,name)){return fail5(`application runtime cannot both export and unset ${name}`)}unsets.add(name)}return Object.freeze({exportEnvironment:Object.freeze(Object.fromEntries(Object.entries(exports2).sort(([left],[right])=>left.localeCompare(right)))),unsetEnvironment:Object.freeze([...unsets].sort())})}function applyManagedStartupCommandEnvironmentPlan(environment,plan){const validated=validateManagedStartupApplicationRuntimePlan(plan);const applied={...environment};for(const name of[...Object.keys(validated.exportEnvironment),...validated.unsetEnvironment]){delete applied[name]}return applied}function exactAgent2(value){if(MANAGED_STARTUP_AGENTS.includes(value)){return value}return fail5(`unsupported agent ${JSON.stringify(value)}`)}function managedTransactionProfile(expectedAgentInput,env=process.env){requireRoot();const expectedAgent=exactAgent2(expectedAgentInput);if(env.NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION!=="1"){fail5("shared-state transactions require a complete managed image")}const encodedProfile=env[MANAGED_STARTUP_PROFILE_ENV];if(!encodedProfile)fail5(`${MANAGED_STARTUP_PROFILE_ENV} is required`);const profile=decodeManagedStartupProfile(encodedProfile);if(profile.agent!==expectedAgent){fail5(`shared-state transaction profile targets ${profile.agent}, expected ${expectedAgent}`)}return profile}function requireRoot(){if(process.geteuid?.()!==0){fail5("managed startup requires container effective uid 0")}}function modeOf3(stat){return stat.mode&511}function requireRootOwnedDirectory(target,mode){let stat;try{stat=import_node_fs3.default.lstatSync(target)}catch{fail5(`required root-owned directory is missing: ${target}`)}if(stat.isSymbolicLink()||!stat.isDirectory()||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==mode){fail5(`${target} must be a root:root directory with mode ${mode.toString(8)}`)}}function ensureRootOwnedDirectory(target,mode=ROOT_OWNED_DIRECTORY_MODE){const parent=import_node_path3.default.dirname(target);const parentStat=import_node_fs3.default.lstatSync(parent);if(parentStat.isSymbolicLink()||!parentStat.isDirectory()||parentStat.uid!==0||parentStat.gid!==0||(modeOf3(parentStat)&18)!==0){fail5(`refusing unsafe parent directory for ${target}`)}try{import_node_fs3.default.mkdirSync(target,{mode});import_node_fs3.default.chownSync(target,0,0);import_node_fs3.default.chmodSync(target,mode)}catch(error){if(error.code!=="EEXIST"){fail5(`could not create ${target}`)}}requireRootOwnedDirectory(target,mode)}function requireSafeExistingRootTarget(target){let stat;try{stat=import_node_fs3.default.lstatSync(target)}catch(error){if(error.code==="ENOENT")return;fail5(`could not inspect ${target}`)}if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0){fail5(`refusing to replace unsafe root-owned file ${target}`)}}function atomicWriteRootFile(target,contents,mode){const parent=import_node_path3.default.dirname(target);const parentStat=import_node_fs3.default.lstatSync(parent);if(parentStat.isSymbolicLink()||!parentStat.isDirectory()||parentStat.uid!==0||parentStat.gid!==0||(modeOf3(parentStat)&18)!==0){fail5(`refusing unsafe root-owned file parent ${parent}`)}requireSafeExistingRootTarget(target);const temporary=import_node_path3.default.join(parent,`.${import_node_path3.default.basename(target)}.${(0,import_node_crypto6.randomBytes)(12).toString("hex")}`);let descriptor;try{descriptor=import_node_fs3.default.openSync(temporary,import_node_fs3.default.constants.O_CREAT|import_node_fs3.default.constants.O_EXCL|import_node_fs3.default.constants.O_WRONLY|import_node_fs3.default.constants.O_NOFOLLOW,384);import_node_fs3.default.fchownSync(descriptor,0,0);import_node_fs3.default.writeFileSync(descriptor,contents);import_node_fs3.default.fchmodSync(descriptor,mode);import_node_fs3.default.fsyncSync(descriptor);import_node_fs3.default.closeSync(descriptor);descriptor=void 0;import_node_fs3.default.renameSync(temporary,target)}catch(error){if(descriptor!==void 0)import_node_fs3.default.closeSync(descriptor);try{import_node_fs3.default.unlinkSync(temporary)}catch{}fail5(`could not atomically write ${target}: ${error.message}`)}const stat=import_node_fs3.default.lstatSync(target);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==mode){fail5(`root-owned output failed metadata verification: ${target}`)}}function removeSafeRootFile(target){requireSafeExistingRootTarget(target);try{import_node_fs3.default.unlinkSync(target)}catch(error){if(error.code!=="ENOENT"){fail5(`could not remove ${target}`)}}}function trustedExecutable(target){try{const stat=import_node_fs3.default.lstatSync(target);return!stat.isSymbolicLink()&&stat.isFile()&&stat.uid===0&&stat.gid===0&&(modeOf3(stat)&18)===0&&(modeOf3(stat)&73)!==0}catch{return false}}function readSandboxIdentity(){const readId=flag=>{const result=(0,import_node_child_process.spawnSync)("/usr/bin/id",[flag,"sandbox"],{encoding:"utf8",env:{PATH:FIXED_PATH}});const value=result.stdout.trim();if(result.status!==0||!/^[1-9][0-9]*$/u.test(value)){fail5("could not resolve the sandbox account")}return value};return{uid:readId("-u"),gid:readId("-g")}}function managedStartupSandboxPrefix(){if(trustedExecutable("/usr/bin/setpriv")){const identity=readSandboxIdentity();return["/usr/bin/setpriv",`--reuid=${identity.uid}`,`--regid=${identity.gid}`,"--init-groups","--"]}return fail5("a trusted setpriv executable is required")}function commandEnvironment(configurationEnvironment,applicationRuntime){const env=applyManagedStartupCommandEnvironmentPlan({...process.env,...configurationEnvironment,HOME:"/sandbox",PATH:FIXED_PATH,NPM_CONFIG_OFFLINE:"true",npm_config_offline:"true",PIP_DISABLE_PIP_VERSION_CHECK:"1",PIP_NO_INDEX:"1",UV_OFFLINE:"1"},applicationRuntime);delete env[MANAGED_STARTUP_PROFILE_ENV];delete env[MANAGED_STARTUP_CA_ENV];return env}function execute(argv,runAs,configurationEnvironment,applicationRuntime,capture=false){if(argv.length===0)fail5("refusing an empty managed startup command");const command=runAs==="sandbox"?[...managedStartupSandboxPrefix(),...argv]:[...argv];const result=(0,import_node_child_process.spawnSync)(command[0],command.slice(1),{encoding:"utf8",env:commandEnvironment(configurationEnvironment,applicationRuntime),stdio:capture?"pipe":"inherit"});if(result.error){fail5(`could not execute ${argv[0]}: ${result.error.message}`)}if(result.status!==0){const detail=capture?`: ${(result.stderr||result.stdout).trim()}`:"";fail5(`${argv[0]} exited with status ${String(result.status??"unknown")}${detail}`)}return{status:result.status,stdout:result.stdout??"",stderr:result.stderr??""}}function generatorCommand(agent){switch(agent){case"openclaw":return["/usr/local/bin/node","/scripts/generate-openclaw-config.mts"];case"hermes":return["/usr/local/bin/node","/opt/nemoclaw-hermes-config/generate-config.ts"];case"langchain-deepagents-code":return["/usr/local/bin/node","/opt/nemoclaw-deepagents-code/generate-config.ts"];case"pi":return["/usr/local/bin/node","/opt/nemoclaw-pi/generate-config.ts"]}}function messagingCommand(agent,phase,mode){return["/usr/local/bin/node","/src/lib/messaging/applier/build/messaging-build-applier.mts","--agent",agent,"--phase",phase,"--mode",mode,...phase==="post-agent-install"?["--managed-startup-runtime"]:[]]}function assertActionAgent(inputAgent,actionAgent){if(inputAgent!==actionAgent){failActionPlan(`action for ${actionAgent} cannot be used by ${inputAgent}`)}}function buildManagedStartupImageActionPlan(input){const inputAgent=exactActionPlanAgent(input.agent);const commands=[];let dashboardActions=0;let generateActions=0;let runtimeMessagingActions=0;let postMessagingActions=0;for(const action of input.actions){switch(action.kind){case"configure-dashboard":{if(action.dashboard.agent!==input.agent){failActionPlan(`dashboard for ${action.dashboard.agent} cannot be used by ${input.agent}`)}dashboardActions+=1;break}case"generate-agent-config":{assertActionAgent(inputAgent,exactActionPlanAgent(action.agent));if(action.runAs!=="sandbox"){failActionPlan("agent configuration generation must run as sandbox")}generateActions+=1;commands.push({action:"generate-agent-config",runAs:action.runAs,argv:generatorCommand(action.agent)});break}case"apply-messaging-plan":{assertActionAgent(inputAgent,exactActionPlanAgent(action.agent));if(action.mode!=="apply"&&action.mode!=="clear"){failActionPlan("messaging intent must be apply or clear")}if(action.phase==="runtime-setup"){if(action.runAs!=="root"){failActionPlan("messaging runtime setup must run as root")}runtimeMessagingActions+=1;commands.push({action:"messaging-runtime-setup",runAs:action.runAs,argv:messagingCommand(action.agent,action.phase,action.mode)})}else if(action.phase==="post-agent-install"){if(action.runAs!=="sandbox"){failActionPlan("messaging post-agent configuration must run as sandbox")}postMessagingActions+=1;commands.push({action:"messaging-post-agent-install",runAs:action.runAs,argv:messagingCommand(action.agent,action.phase,action.mode)})}else{failActionPlan("unsupported messaging construction phase")}break}default:failActionPlan("unsupported managed startup construction action")}}if(dashboardActions!==1){failActionPlan("exactly one dashboard construction action is required")}if(generateActions!==1){failActionPlan("exactly one agent config construction action is required")}const supportsMessaging=MANAGED_STARTUP_MESSAGING_AGENTS.includes(inputAgent);const expectedMessagingActions=supportsMessaging?1:0;if(runtimeMessagingActions!==expectedMessagingActions||postMessagingActions!==expectedMessagingActions){failActionPlan(`${inputAgent} requires ${String(expectedMessagingActions)} action for each messaging phase`)}const expectedOrder=supportsMessaging?["messaging-runtime-setup","generate-agent-config","messaging-post-agent-install"]:["generate-agent-config"];if(commands.some((command,index)=>command.action!==expectedOrder[index])){failActionPlan(`${inputAgent} image actions are not in the required construction order`)}return Object.freeze(commands.map(command=>Object.freeze({...command,argv:Object.freeze([...command.argv])})))}function prepareMessagingRuntimeTarget(mode){if(mode==="clear"){removeSafeRootFile(MESSAGING_RUNTIME_PLAN_FILE);return}requireSafeExistingRootTarget(MESSAGING_RUNTIME_PLAN_FILE);try{import_node_fs3.default.unlinkSync(MESSAGING_RUNTIME_PLAN_FILE)}catch(error){if(error.code!=="ENOENT"){fail5("could not prepare the messaging runtime-plan target")}}}function verifyMessagingRuntimeTarget(mode){if(mode==="clear"){if(import_node_fs3.default.existsSync(MESSAGING_RUNTIME_PLAN_FILE)){fail5("clear messaging profile left a runtime-plan artifact")}return}const stat=import_node_fs3.default.lstatSync(MESSAGING_RUNTIME_PLAN_FILE);if(stat.isSymbolicLink()||!stat.isFile()||stat.nlink!==1||stat.uid!==0||stat.gid!==0||modeOf3(stat)!==420){fail5("messaging runtime-plan artifact failed root ownership validation")}}function runInternalSandboxAction(action,configurationEnvironment,applicationRuntime,extraEnvironment={}){execute(["/usr/local/bin/node",MANAGED_STARTUP_RUNTIME_EXECUTABLE,`--internal-${action}`],"sandbox",{...configurationEnvironment,...extraEnvironment},applicationRuntime)}function sealOpenClawConfiguration(configurationEnvironment,applicationRuntime){const validation=execute(["/usr/local/bin/openclaw","config","validate","--json"],"sandbox",{...configurationEnvironment,OPENCLAW_CONFIG_PATH:"/sandbox/.openclaw/openclaw.json"},applicationRuntime,true);let parsed;try{parsed=JSON.parse(validation.stdout)}catch{fail5("OpenClaw config validation did not emit JSON")}if(typeof parsed!=="object"||parsed===null||parsed.valid!==true){fail5("OpenClaw rejected the generated managed startup config")}runInternalSandboxAction("write-openclaw-hash",configurationEnvironment,applicationRuntime)}function sameStableFileMetadata(left,right){return left.dev===right.dev&&left.ino===right.ino&&left.mode===right.mode&&left.nlink===right.nlink&&left.uid===right.uid&&left.gid===right.gid&&left.size===right.size&&left.mtimeNs===right.mtimeNs&&left.ctimeNs===right.ctimeNs}function readStableRegularFileSnapshot(target,maxBytes){if(typeof import_node_fs3.default.constants.O_NOFOLLOW!=="number"){fail5("O_NOFOLLOW is unavailable for managed startup file reads")}const nonblock=typeof import_node_fs3.default.constants.O_NONBLOCK==="number"?import_node_fs3.default.constants.O_NONBLOCK:0;let descriptor;try{descriptor=import_node_fs3.default.openSync(target,import_node_fs3.default.constants.O_RDONLY|import_node_fs3.default.constants.O_NOFOLLOW|nonblock)}catch(error){if(error.code==="ENOENT")throw error;fail5(`refusing unsafe or unreadable file ${target}`)}try{const before=import_node_fs3.default.fstatSync(descriptor,{bigint:true});if(!before.isFile()||before.nlink!==1n||before.size<1n||before.size>BigInt(maxBytes)){fail5(`refusing unsafe or oversized file ${target}`)}const bytes=Buffer.alloc(Number(before.size));let offset=0;while(offset`${block.trim()} `)}function managedSystemCaAnchorNames(){try{import_node_fs3.default.lstatSync(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY)}catch(error){if(error.code==="ENOENT")return[];fail5("could not inspect the managed system CA anchor directory")}requireRootOwnedDirectory(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY,ROOT_OWNED_DIRECTORY_MODE);try{return import_node_fs3.default.readdirSync(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY).filter(name=>MANAGED_STARTUP_SYSTEM_CA_ANCHOR_RE.test(name)).sort()}catch(error){fail5("could not inspect the managed system CA anchors")}}function refreshSystemCaBundle(){if(!trustedExecutable(UPDATE_CA_CERTIFICATES_EXECUTABLE)){fail5(`a trusted ${UPDATE_CA_CERTIFICATES_EXECUTABLE} executable is required`)}const result=(0,import_node_child_process.spawnSync)(UPDATE_CA_CERTIFICATES_EXECUTABLE,[],{encoding:"utf8",env:{PATH:FIXED_PATH},stdio:"inherit"});if(result.error){fail5(`could not execute ${UPDATE_CA_CERTIFICATES_EXECUTABLE}: ${result.error.message}`)}if(result.status!==0){fail5(`${UPDATE_CA_CERTIFICATES_EXECUTABLE} exited with status ${String(result.status??"unknown")}`)}}function requireSystemCaBundleContains(blocks){const systemBundle=safeTrustBundle(SYSTEM_CA_BUNDLE_FILE);if(systemBundle===null)fail5("the refreshed system CA bundle is missing");const systemBlocks=systemBundle.toString("utf8").match(PEM_CERTIFICATE_RE_GLOBAL)??[];const systemFingerprints=new Set;for(const block of systemBlocks){try{systemFingerprints.add(new import_node_crypto6.X509Certificate(block).fingerprint256)}catch{fail5("the refreshed system CA bundle contains an invalid certificate")}}for(const block of blocks){if(!systemFingerprints.has(new import_node_crypto6.X509Certificate(block).fingerprint256)){fail5("the refreshed system CA bundle does not contain the corporate CA")}}}function installCorporateCaSystemAnchors(corporateCaPath){const existingNames=managedSystemCaAnchorNames();if(corporateCaPath===null){for(const name of existingNames){removeSafeRootFile(import_node_path3.default.join(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY,name))}refreshSystemCaBundle();return}ensureRootOwnedDirectory(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY);const blocks=corporateCaCertificateBlocks(corporateCaPath);const expectedNames=blocks.map((_block,index)=>`nemoclaw-corporate-ca-${String(index+1).padStart(2,"0")}.crt`);for(const name of existingNames){if(!expectedNames.includes(name)){removeSafeRootFile(import_node_path3.default.join(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY,name))}}for(const[index,name]of expectedNames.entries()){atomicWriteRootFile(import_node_path3.default.join(MANAGED_STARTUP_SYSTEM_CA_ANCHOR_DIRECTORY,name),blocks[index],292)}refreshSystemCaBundle();requireSystemCaBundleContains(blocks)}function safeTrustBundle(target){try{const{bytes,stat}=readStableRegularFileSnapshot(target,MAX_TRUST_BUNDLE_BYTES);if(Number(stat.mode&0o022n)!==0){fail5(`refusing unsafe trust bundle ${target}`)}return bytes}catch(error){if(error.code==="ENOENT")return null;throw error}}function mergeCorporateCa(corporateCaPath){if(corporateCaPath===null){removeSafeRootFile(MANAGED_STARTUP_MERGED_CA_FILE);return false}const corporate=readStableRegularFile(corporateCaPath,128*1024);const candidates=["/etc/openshell-tls/ca-bundle.pem",process.env.SSL_CERT_FILE??"","/etc/ssl/certs/ca-certificates.crt"].filter((candidate,index,values)=>candidate&&candidate!==MANAGED_STARTUP_MERGED_CA_FILE&&values.indexOf(candidate)===index);let base=null;for(const candidate of candidates){base=safeTrustBundle(candidate);if(base)break}const merged=Buffer.concat([...base?[base,Buffer.from("\n","utf8")]:[],corporate,...corporate.at(-1)===10?[]:[Buffer.from("\n","utf8")]]);atomicWriteRootFile(MANAGED_STARTUP_MERGED_CA_FILE,merged,292);return true}function shellSingleQuote(value){if(value.includes("\0")||/[\r\n]/u.test(value)){fail5("runtime environment values must be single-line text")}return`'${value.replaceAll("'",`'"'"'`)}'`}function serializeManagedStartupRuntimeEnvironment(environment,corporateCaMerged,configurationEnvironment={},applicationRuntime={exportEnvironment:{},unsetEnvironment:[]}){const{output,unsetNames}=materializeManagedStartupRuntimeEnvironment(environment,corporateCaMerged,configurationEnvironment,applicationRuntime);const unsetLines=unsetNames.map(name=>`unset ${name}`);const exportLines=Object.entries(output).sort(([left],[right])=>left.localeCompare(right)).map(([name,value])=>`export ${name}=${shellSingleQuote(value)}`);return`${[...unsetLines,...exportLines].join("\n")} `}function materializeManagedStartupRuntimeEnvironment(environment,corporateCaMerged,configurationEnvironment={},applicationRuntime={exportEnvironment:{},unsetEnvironment:[]}){const validatedApplicationRuntime=validateManagedStartupApplicationRuntimePlan(applicationRuntime);const output={...environment,...validatedApplicationRuntime.exportEnvironment,NEMOCLAW_MANAGED_STARTUP_APPLIED:"1"};if(corporateCaMerged){for(const name of MANAGED_STARTUP_TLS_ENV_NAMES){delete output[name]}output._NEMOCLAW_CORPORATE_CA_MERGED="1"}for(const name of[...Object.keys(configurationEnvironment),...Object.keys(output)]){if(!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){fail5(`invalid runtime environment key ${JSON.stringify(name)}`)}}const unsetNames=new Set([...Object.keys(configurationEnvironment).filter(name=>!Object.hasOwn(output,name)&&(!corporateCaMerged||!MANAGED_STARTUP_TLS_ENV_NAMES.has(name))),...validatedApplicationRuntime.unsetEnvironment.filter(name=>!corporateCaMerged||!MANAGED_STARTUP_TLS_ENV_NAMES.has(name))]);for(const name of validatedApplicationRuntime.unsetEnvironment){if(Object.hasOwn(output,name)){fail5(`runtime environment cannot both export and unset ${name}`)}}for(const name of unsetNames){if(!/^[A-Za-z_][A-Za-z0-9_]*$/u.test(name)){fail5(`invalid runtime environment key ${JSON.stringify(name)}`)}}return{output,unsetNames:[...unsetNames].sort()}}function serializeManagedStartupCompletionMarker(marker){if(marker.schemaVersion!==MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION||!MANAGED_STARTUP_AGENTS.includes(marker.agent)||!SHA256_RE4.test(marker.profileFingerprint)||!SHA256_RE4.test(marker.runtimeEnvironmentSha256)||typeof marker.corporateCaMerged!=="boolean"){fail5("managed startup completion marker is invalid")}return`${JSON.stringify({agent:marker.agent,corporateCaMerged:marker.corporateCaMerged,profileFingerprint:marker.profileFingerprint,runtimeEnvironmentSha256:marker.runtimeEnvironmentSha256,schemaVersion:marker.schemaVersion})} `}function parseManagedStartupCompletionMarker(text){let parsed;try{parsed=JSON.parse(text)}catch{fail5("managed startup completion marker is not valid JSON")}if(typeof parsed!=="object"||parsed===null||Array.isArray(parsed)){fail5("managed startup completion marker must be an object")}const record=parsed;const expectedKeys=["agent","corporateCaMerged","profileFingerprint","runtimeEnvironmentSha256","schemaVersion"];if(Object.keys(record).sort().join(",")!==expectedKeys.sort().join(",")||record.schemaVersion!==MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION||typeof record.agent!=="string"||!MANAGED_STARTUP_AGENTS.includes(record.agent)||typeof record.profileFingerprint!=="string"||!SHA256_RE4.test(record.profileFingerprint)||typeof record.runtimeEnvironmentSha256!=="string"||!SHA256_RE4.test(record.runtimeEnvironmentSha256)||typeof record.corporateCaMerged!=="boolean"){fail5("managed startup completion marker has an invalid schema")}const marker={schemaVersion:MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION,agent:record.agent,profileFingerprint:record.profileFingerprint,runtimeEnvironmentSha256:record.runtimeEnvironmentSha256,corporateCaMerged:record.corporateCaMerged};if(serializeManagedStartupCompletionMarker(marker)!==text){fail5("managed startup completion marker is not canonical")}return marker}function verifyManagedStartupImageCompletion(expectedAgentInput,expectedFingerprint,completionFile=MANAGED_STARTUP_COMPLETION_FILE,runtimeEnvironmentFile=MANAGED_STARTUP_RUNTIME_ENV_FILE){const expectedAgent=exactAgent2(expectedAgentInput);if(!SHA256_RE4.test(expectedFingerprint)){fail5("startup completion expected profile fingerprint is invalid")}const{bytes,stat}=readStableRegularFileSnapshot(completionFile,MAX_MANAGED_STARTUP_COMPLETION_BYTES);if(stat.nlink!==1n||stat.uid!==0n||stat.gid!==0n||Number(stat.mode&0o777n)!==292){fail5("managed startup completion marker must be root:root mode 0444")}const marker=parseManagedStartupCompletionMarker(bytes.toString("utf8"));if(marker.agent!==expectedAgent||marker.profileFingerprint!==expectedFingerprint){fail5("managed startup completion marker does not match the requested profile")}const runtimeEnvironment=readStableRegularFileSnapshot(runtimeEnvironmentFile,MAX_MANAGED_STARTUP_RUNTIME_ENVIRONMENT_BYTES);if(runtimeEnvironment.stat.nlink!==1n||runtimeEnvironment.stat.uid!==0n||runtimeEnvironment.stat.gid!==0n||Number(runtimeEnvironment.stat.mode&0o777n)!==292){fail5("managed startup runtime environment must be root:root mode 0444")}const runtimeEnvironmentSha256=(0,import_node_crypto6.createHash)("sha256").update(runtimeEnvironment.bytes).digest("hex");if(runtimeEnvironmentSha256!==marker.runtimeEnvironmentSha256){fail5("managed startup completion marker runtime environment digest mismatch")}return{agent:expectedAgent,fingerprint:expectedFingerprint}}function waitForManagedStartupImageCompletion(expectedAgentInput,expectedFingerprint,timeoutSeconds=600){if(!Number.isSafeInteger(timeoutSeconds)||timeoutSeconds<1||timeoutSeconds>3600){fail5("startup completion wait timeout must be an integer from 1 to 3600 seconds")}const deadline=Date.now()+timeoutSeconds*1e3;while(true){try{return verifyManagedStartupImageCompletion(expectedAgentInput,expectedFingerprint)}catch(error){if(error.code!=="ENOENT")throw error;if(Date.now()>=deadline){fail5(`startup completion was not published within ${String(timeoutSeconds)} seconds`)}Atomics.wait(new Int32Array(new SharedArrayBuffer(4)),0,0,250)}}}function applyAdapter(context,mapped){if(mapped.agent!==context.agent){fail5(`mapped ${mapped.agent} environment for ${context.agent}`)}const commandPlan=buildManagedStartupImageActionPlan({agent:mapped.agent,actions:mapped.actions});let commandIndex=0;for(const action of mapped.actions){if(action.kind==="configure-dashboard")continue;const command=commandPlan[commandIndex];if(!command)fail5(`missing image command for ${action.kind}`);commandIndex+=1;if(action.kind==="apply-messaging-plan"){if(action.phase==="runtime-setup"){prepareMessagingRuntimeTarget(action.mode)}execute(command.argv,command.runAs,mapped.configurationEnvironment,mapped.applicationRuntime);if(action.phase==="runtime-setup"){verifyMessagingRuntimeTarget(action.mode)}continue}execute(command.argv,command.runAs,mapped.configurationEnvironment,mapped.applicationRuntime)}if(commandIndex!==commandPlan.length){fail5("image action plan contains an unmatched command")}switch(context.agent){case"openclaw":sealOpenClawConfiguration(mapped.configurationEnvironment,mapped.applicationRuntime);break;case"hermes":installHermesManagedPolicy();sealHermesConfiguration(mapped.configurationEnvironment,mapped.applicationRuntime);normalizeHermesManagedConfiguration();break;case"langchain-deepagents-code":break}installRootOwnedMaterials(mapped.materials);installCorporateCa(context.corporateCaPath);installCorporateCaSystemAnchors(context.corporateCaPath);mergeCorporateCa(context.corporateCaPath)}function adapters(mapped){return MANAGED_STARTUP_AGENTS.map(agent=>({agent,apply:context=>applyAdapter(context,mapped)}))}async function applyManagedStartupImageProfile(expectedAgentInput,env=process.env){requireRoot();const expectedAgent=exactAgent2(expectedAgentInput);if(env.NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION!=="1"){fail5("startup profiles require a complete managed image")}const encodedProfile=env[MANAGED_STARTUP_PROFILE_ENV];if(!encodedProfile)fail5(`${MANAGED_STARTUP_PROFILE_ENV} is required`);let profile;try{profile=decodeManagedStartupProfile(encodedProfile)}catch(error){fail5(error.message)}if(profile.agent!==expectedAgent){fail5(`managed startup profile targets ${profile.agent}, expected ${expectedAgent}`)}const mapped=mapManagedStartupProfileToAgentEnvironment(profile,env);validateManagedStartupApplicationRuntimePlan(mapped.applicationRuntime);ensureRootOwnedDirectory(ROOT_STATE_PARENT);ensureRootOwnedDirectory(ROOT_RUNTIME_DIRECTORY);const result=await coordinateManagedStartupApplication({encodedProfile,expectedAgent,...env[MANAGED_STARTUP_CA_ENV]===void 0?{}:{corporateCaB64:env[MANAGED_STARTUP_CA_ENV]}},adapters(mapped));if(mapped.agent!==result.application.profile.agent){fail5(`mapped ${mapped.agent} environment for ${result.application.profile.agent}`)}if(expectedAgent==="hermes"&&!result.adapterApplied){normalizeHermesManagedConfiguration()}let corporateCaMerged;if(result.adapterApplied){corporateCaMerged=result.application.corporateCaPath!==null}else{verifyRootOwnedMaterials(mapped.materials);if(result.application.corporateCaPath===null){if(import_node_fs3.default.existsSync(MANAGED_STARTUP_CORPORATE_CA_FILE)){fail5("committed profile without a corporate CA has a stale CA material")}}else{const expected=readStableRegularFile(result.application.corporateCaPath,128*1024);const installed=readStableRegularFile(MANAGED_STARTUP_CORPORATE_CA_FILE,128*1024);if(!expected.equals(installed)){fail5("committed corporate CA material drifted")}}installCorporateCaSystemAnchors(result.application.corporateCaPath);corporateCaMerged=mergeCorporateCa(result.application.corporateCaPath)}const runtimeEnvironment=serializeManagedStartupRuntimeEnvironment(mapped.runtimeEnvironment,corporateCaMerged,mapped.configurationEnvironment,mapped.applicationRuntime);atomicWriteRootFile(MANAGED_STARTUP_RUNTIME_ENV_FILE,runtimeEnvironment,292);atomicWriteRootFile(MANAGED_STARTUP_COMPLETION_FILE,serializeManagedStartupCompletionMarker({schemaVersion:MANAGED_STARTUP_COMPLETION_SCHEMA_VERSION,agent:expectedAgent,profileFingerprint:result.application.fingerprint,runtimeEnvironmentSha256:(0,import_node_crypto6.createHash)("sha256").update(runtimeEnvironment,"utf8").digest("hex"),corporateCaMerged}),292);return{agent:expectedAgent,adapterApplied:result.adapterApplied,fingerprint:result.application.fingerprint,runtimeEnvironmentFile:MANAGED_STARTUP_RUNTIME_ENV_FILE}}function completionAlreadyPublished(request){try{verifyManagedStartupImageCompletion(request.agent,request.profileFingerprint);return true}catch(error){if(error.code==="ENOENT")return false;throw error}}async function applyManagedStartupRootRequest(request,env=process.env,options={}){requireRoot();const profile=decodeManagedStartupProfile(request.encodedProfile);if(profile.agent!==request.agent||fingerprintManagedStartupProfile(profile)!==request.profileFingerprint){fail5("root application request identity does not match its profile")}const imageEnvironment={HOME:"/root",PATH:FIXED_PATH,NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION:"1",...selectManagedStartupApplicationRuntimeEnvironment(env),[MANAGED_STARTUP_PROFILE_ENV]:request.encodedProfile,...request.corporateCaB64===null?{}:{[MANAGED_STARTUP_CA_ENV]:request.corporateCaB64}};mapManagedStartupProfileToAgentEnvironment(profile,imageEnvironment);const alreadyPublished=completionAlreadyPublished(request);const bootstrapIdentity=options.bootstrapIdentity??null;const transactionStatus=alreadyPublished&&bootstrapIdentity!==null?getManagedStartupSharedStateTransactionStatus({agent:request.agent,profileFingerprint:request.profileFingerprint,bootstrapIdentity}):null;if(transactionStatus==="none"){fail5("completed startup profile has no shared-state authority for this bootstrap attempt")}if(!alreadyPublished){ensureRootOwnedDirectory(ROOT_STATE_PARENT);beginManagedStartupSharedStateTransaction(profile,{bootstrapIdentity})}const result=await applyManagedStartupImageProfile(request.agent,imageEnvironment);return{...result,transactionPending:!alreadyPublished||transactionStatus==="pending"}}function readBoundedRootApplyStdin(){const chunks=[];let total=0;while(true){const chunk=Buffer.alloc(16*1024);const read=import_node_fs3.default.readSync(0,chunk,0,chunk.length,null);if(read===0)break;total+=read;if(total>MANAGED_STARTUP_ROOT_APPLY_MAX_BYTES){fail5("root application stdin exceeds its bounded transport")}chunks.push(chunk.subarray(0,read))}const bytes=Buffer.concat(chunks,total);const text=bytes.toString("utf8");if(text.includes("\0")||!Buffer.from(text,"utf8").equals(bytes)){fail5("root application stdin must be valid UTF-8 without NUL bytes")}return text}function writeSandboxFileAtomically(target,contents,mode){const parent=import_node_path3.default.dirname(target);const parentStat=import_node_fs3.default.lstatSync(parent);if(parentStat.isSymbolicLink()||!parentStat.isDirectory()||parentStat.uid!==process.geteuid?.()||parentStat.gid!==process.getegid?.()){fail5(`refusing unsafe sandbox-owned directory ${parent}`)}const temporary=import_node_path3.default.join(parent,`.${import_node_path3.default.basename(target)}.${(0,import_node_crypto6.randomBytes)(12).toString("hex")}`);let descriptor;try{descriptor=import_node_fs3.default.openSync(temporary,import_node_fs3.default.constants.O_CREAT|import_node_fs3.default.constants.O_EXCL|import_node_fs3.default.constants.O_WRONLY|import_node_fs3.default.constants.O_NOFOLLOW,384);import_node_fs3.default.writeFileSync(descriptor,contents);import_node_fs3.default.fchmodSync(descriptor,mode);import_node_fs3.default.fsyncSync(descriptor);import_node_fs3.default.closeSync(descriptor);descriptor=void 0;import_node_fs3.default.renameSync(temporary,target)}catch(error){if(descriptor!==void 0)import_node_fs3.default.closeSync(descriptor);try{import_node_fs3.default.unlinkSync(temporary)}catch{}fail5(`could not write sandbox-owned file ${target}: ${error.message}`)}}function internalWriteOpenClawHash(){if(process.geteuid?.()===0)fail5("sandbox hash writer must not run as root");const configPath="/sandbox/.openclaw/openclaw.json";const config=readStableRegularFile(configPath,16*1024*1024);const text=`${(0,import_node_crypto6.createHash)("sha256").update(config).digest("hex")} openclaw.json diff --git a/tools/pr-review-advisor/local-review.mts b/tools/pr-review-advisor/local-review.mts index fdd3fda0448..8d08eca8be3 100755 --- a/tools/pr-review-advisor/local-review.mts +++ b/tools/pr-review-advisor/local-review.mts @@ -176,7 +176,7 @@ async function main(): Promise<{ code: number | null; signal: NodeJS.Signals | n throw new Error("npm failed while preparing the trusted local review checkout"); result = await run( process.execPath, - ["--experimental-strip-types", "--no-warnings", path.join(checkout, IMPLEMENTATION), source], + ["--no-warnings", path.join(checkout, IMPLEMENTATION), source], { cwd: checkout, env, inherit: true }, ); return { code: result.code, signal: received ?? result.signal }; diff --git a/tools/pr-review-advisor/openshell.mts b/tools/pr-review-advisor/openshell.mts index 95418d22dff..e12aea36013 100755 --- a/tools/pr-review-advisor/openshell.mts +++ b/tools/pr-review-advisor/openshell.mts @@ -305,7 +305,6 @@ export function createAdvisorSandbox( uploads: [], command: [ "/usr/bin/node", - "--experimental-strip-types", "--no-warnings", `${SANDBOX_ADVISOR_DIR}/tools/pr-review-advisor/openshell.mts`, "initialize", @@ -384,7 +383,6 @@ export function runAdvisorSandboxAsync( }, command: [ "/usr/bin/node", - "--experimental-strip-types", "--no-warnings", `${SANDBOX_ADVISOR_DIR}/tools/pr-review-advisor/run-specialist.mts`, "--base", From 35a116ac2995c35349193b3134b6b5dc76ba3d9d Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Wed, 9 Sep 2026 10:59:44 -0700 Subject: [PATCH 2/4] test: refresh Pi qualification and align CLI timeout budgets Signed-off-by: Carlos Villela --- ci/pi-agent-qualification-v1-linux-amd64.json | 8 ++++---- ci/pi-agent-qualification-v1-linux-arm64.json | 8 ++++---- src/lib/agent/candidate-authority.ts | 4 ++-- test/package-contract/cli/public-cli-contracts.test.ts | 4 +++- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/ci/pi-agent-qualification-v1-linux-amd64.json b/ci/pi-agent-qualification-v1-linux-amd64.json index 3d142d3af13..9c1a7002af0 100644 --- a/ci/pi-agent-qualification-v1-linux-amd64.json +++ b/ci/pi-agent-qualification-v1-linux-amd64.json @@ -3,13 +3,13 @@ "agent": "pi", "platform": "linux/amd64", "image": "ghcr.io/nvidia/nemoclaw/pi-sandbox", - "digest": "sha256:32416a25b4adf069edf71d8b022ed5a3eb980cdb259e6580a43978414b228b6e", - "reference": "ghcr.io/nvidia/nemoclaw/pi-sandbox@sha256:32416a25b4adf069edf71d8b022ed5a3eb980cdb259e6580a43978414b228b6e", + "digest": "sha256:fe933d8331387fe05a2ffad135dd493ca75f210343728e03b69c1a9ea7d58008", + "reference": "ghcr.io/nvidia/nemoclaw/pi-sandbox@sha256:fe933d8331387fe05a2ffad135dd493ca75f210343728e03b69c1a9ea7d58008", "source": { "repository": "NVIDIA/NemoClaw", - "revision": "375c76a4646c8f4f9537ac9c18370e519354bbc7", + "revision": "609d60a3562142350d6afb3f824b0248624a00d0", "release": "v0.1.0", - "cohort": "ghrun-34305816131-1" + "cohort": "ghrun-34384136357-1" }, "startupProfileContractVersion": 1, "capabilityContractVersion": 1 diff --git a/ci/pi-agent-qualification-v1-linux-arm64.json b/ci/pi-agent-qualification-v1-linux-arm64.json index bb6b8d52f00..3af467464e7 100644 --- a/ci/pi-agent-qualification-v1-linux-arm64.json +++ b/ci/pi-agent-qualification-v1-linux-arm64.json @@ -3,13 +3,13 @@ "agent": "pi", "platform": "linux/arm64", "image": "ghcr.io/nvidia/nemoclaw/pi-sandbox", - "digest": "sha256:9bd80aa090f8bc51db8b1eead1a774d01d926ad0dc2d1ed629447db3f4dd7c72", - "reference": "ghcr.io/nvidia/nemoclaw/pi-sandbox@sha256:9bd80aa090f8bc51db8b1eead1a774d01d926ad0dc2d1ed629447db3f4dd7c72", + "digest": "sha256:dd47411d99704bc8464899bea5e5f30b5cdda862af64b281d62f38121adeec01", + "reference": "ghcr.io/nvidia/nemoclaw/pi-sandbox@sha256:dd47411d99704bc8464899bea5e5f30b5cdda862af64b281d62f38121adeec01", "source": { "repository": "NVIDIA/NemoClaw", - "revision": "375c76a4646c8f4f9537ac9c18370e519354bbc7", + "revision": "609d60a3562142350d6afb3f824b0248624a00d0", "release": "v0.1.0", - "cohort": "ghrun-34305816131-1" + "cohort": "ghrun-34384136357-1" }, "startupProfileContractVersion": 1, "capabilityContractVersion": 1 diff --git a/src/lib/agent/candidate-authority.ts b/src/lib/agent/candidate-authority.ts index c284790d74b..df39077962b 100644 --- a/src/lib/agent/candidate-authority.ts +++ b/src/lib/agent/candidate-authority.ts @@ -13,8 +13,8 @@ export const CANDIDATE_QUALIFICATION_RECEIPT_DIGESTS: Readonly< Record > = Object.freeze({ pi: Object.freeze([ - "147667683238332c62c6df3fb1e56056272f47cc7a64bd30fe50eee9bf041685", - "e3ed23b52ec8091cb30a4a04c53b2201ef8c1e0c34a58d7f46013108759dcb0e", + "248bd6ee38c2d3d07f2a4744ba131fd40157aa6e2b7aa7d9867066ff8e5ce7b8", + "19a628fa3fba1637fcb7aa13428d4ddbf5d6fdc6e377639c0110296ad4cd1c07", ]), }); diff --git a/test/package-contract/cli/public-cli-contracts.test.ts b/test/package-contract/cli/public-cli-contracts.test.ts index ba86e64aa64..5727295740d 100644 --- a/test/package-contract/cli/public-cli-contracts.test.ts +++ b/test/package-contract/cli/public-cli-contracts.test.ts @@ -121,7 +121,9 @@ function readCliInvocations(fixture: CliParityFixture): string[] { } describe("public compiled CLI contracts", () => { - it("prints the public NemoClaw version prefix (#7616)", () => { + it("prints the public NemoClaw version prefix (#7616)", { + timeout: 35_000, + }, () => { const result = spawnSync(process.execPath, [CLI_ENTRYPOINT, "--version"], { cwd: REPO_ROOT, encoding: "utf-8", From 34b1cb09f23e2ffdef7c771a1f4c0b5418dab82d Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Wed, 9 Sep 2026 11:03:18 -0700 Subject: [PATCH 3/4] ci: require supported Node versions for native TypeScript Signed-off-by: Carlos Villela --- .github/actions/ci-static-checks/action.yaml | 2 +- .github/workflows/candidate-compatibility.yaml | 6 +++--- .github/workflows/e2e-main-retry.yaml | 4 ++-- .github/workflows/e2e.yaml | 18 +++++++++--------- .github/workflows/hosted-runner-recovery.yaml | 2 +- .../workflows/openshell-sdk-package-pr.yaml | 2 +- .github/workflows/portable-profile-e2e.yaml | 2 +- .github/workflows/post-merge-docs.yaml | 4 ++-- .github/workflows/pr-merge-conflict-fixer.yaml | 6 +++--- .github/workflows/pr-review-advisor.yaml | 6 +++--- .github/workflows/pr-self-hosted.yaml | 2 +- .github/workflows/pr.yaml | 6 +++--- .../hosted-runner-recovery-workflow.test.ts | 2 +- .../jetson-managed-revision-boundary.test.ts | 2 +- .../hermes-gpu-startup-workflow-boundary.mts | 2 +- .../e2e/mcp-dev-workflow-boundary-digests.mts | 4 ++-- tools/e2e/mcp-workflow-boundary.mts | 2 +- tools/e2e/operations-workflow-boundary.mts | 2 +- tools/e2e/workflow-boundary.mts | 8 ++++---- 19 files changed, 41 insertions(+), 41 deletions(-) diff --git a/.github/actions/ci-static-checks/action.yaml b/.github/actions/ci-static-checks/action.yaml index 5f3f984640b..75f1539a9d8 100644 --- a/.github/actions/ci-static-checks/action.yaml +++ b/.github/actions/ci-static-checks/action.yaml @@ -10,7 +10,7 @@ runs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: | package-lock.json diff --git a/.github/workflows/candidate-compatibility.yaml b/.github/workflows/candidate-compatibility.yaml index 3f13d33ac5e..3c11080ebd2 100644 --- a/.github/workflows/candidate-compatibility.yaml +++ b/.github/workflows/candidate-compatibility.yaml @@ -57,7 +57,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - id: identity name: Resolve official candidate provenance @@ -142,7 +142,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: candidate-source/package-lock.json @@ -270,7 +270,7 @@ jobs: - name: Set up Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: candidate-source/package-lock.json diff --git a/.github/workflows/e2e-main-retry.yaml b/.github/workflows/e2e-main-retry.yaml index 2667ad60c45..c0534a99518 100644 --- a/.github/workflows/e2e-main-retry.yaml +++ b/.github/workflows/e2e-main-retry.yaml @@ -47,7 +47,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Evaluate main E2E retry env: @@ -96,7 +96,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Build advisory same-commit reliability report env: diff --git a/.github/workflows/e2e.yaml b/.github/workflows/e2e.yaml index 4d5846ddee8..dfee991bb15 100644 --- a/.github/workflows/e2e.yaml +++ b/.github/workflows/e2e.yaml @@ -143,7 +143,7 @@ jobs: - name: Set up Node for reviewed package download uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" registry-url: https://npm.pkg.github.com scope: "@nvidia" @@ -237,7 +237,7 @@ jobs: - name: Set up Node for publication verification uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - id: select_pr_source name: Resolve exact PR managed-image publication @@ -643,7 +643,7 @@ jobs: - name: Set up Node for trusted E2E planning uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - name: Install trusted E2E planner dependencies run: npm ci --ignore-scripts --no-audit --no-fund @@ -915,7 +915,7 @@ jobs: - name: Set up Node for trusted qualification planning uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - id: source name: Authenticate the candidate and dispatch artifact @@ -3966,7 +3966,7 @@ jobs: - name: Set up Node for OpenShell dev artifact resolution uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - id: resolve_openshell_dev_artifact name: Resolve immutable OpenShell dev artifact @@ -4026,7 +4026,7 @@ jobs: - name: Set up Node.js for trusted OpenShell verification uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" package-manager-cache: false - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -4714,7 +4714,7 @@ jobs: - name: Set up Node for trusted llama.cpp plan compilation uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" cache: npm - name: Install trusted llama.cpp plan dependencies @@ -5484,7 +5484,7 @@ jobs: ENV: /dev/null NODE_OPTIONS: "" with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Recover Docker CLI before native Podman E2E if: ${{ matrix.runtime_provider == 'podman' }} @@ -5668,7 +5668,7 @@ jobs: - name: Set up Node for Jetson controller uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - name: Dispatch exact commit to Jetson through operator backend env: diff --git a/.github/workflows/hosted-runner-recovery.yaml b/.github/workflows/hosted-runner-recovery.yaml index 785559dc385..da568b44c14 100644 --- a/.github/workflows/hosted-runner-recovery.yaml +++ b/.github/workflows/hosted-runner-recovery.yaml @@ -47,7 +47,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Evaluate exact hosted-runner-loss evidence env: diff --git a/.github/workflows/openshell-sdk-package-pr.yaml b/.github/workflows/openshell-sdk-package-pr.yaml index d47416178ee..2304e20e9c1 100644 --- a/.github/workflows/openshell-sdk-package-pr.yaml +++ b/.github/workflows/openshell-sdk-package-pr.yaml @@ -46,7 +46,7 @@ jobs: - name: Setup Node.js for reviewed package download uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" registry-url: https://npm.pkg.github.com scope: "@nvidia" diff --git a/.github/workflows/portable-profile-e2e.yaml b/.github/workflows/portable-profile-e2e.yaml index dc07c6a87de..35aff253b5d 100644 --- a/.github/workflows/portable-profile-e2e.yaml +++ b/.github/workflows/portable-profile-e2e.yaml @@ -74,7 +74,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm - name: Install root dependencies diff --git a/.github/workflows/post-merge-docs.yaml b/.github/workflows/post-merge-docs.yaml index f655c110d5e..969741ae13d 100644 --- a/.github/workflows/post-merge-docs.yaml +++ b/.github/workflows/post-merge-docs.yaml @@ -73,7 +73,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Find the documentation range working-directory: trusted @@ -171,7 +171,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: diff --git a/.github/workflows/pr-merge-conflict-fixer.yaml b/.github/workflows/pr-merge-conflict-fixer.yaml index 72d29f0f7f5..fe45fa28415 100644 --- a/.github/workflows/pr-merge-conflict-fixer.yaml +++ b/.github/workflows/pr-merge-conflict-fixer.yaml @@ -33,7 +33,7 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - id: scan name: Reproduce PR merges @@ -72,7 +72,7 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - id: prepare name: Reproduce the recorded conflict @@ -144,7 +144,7 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - id: download name: Download the resolution patch diff --git a/.github/workflows/pr-review-advisor.yaml b/.github/workflows/pr-review-advisor.yaml index 709f888861d..832aa175c36 100644 --- a/.github/workflows/pr-review-advisor.yaml +++ b/.github/workflows/pr-review-advisor.yaml @@ -167,7 +167,7 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: advisor/package-lock.json - name: Install locked runtime @@ -270,7 +270,7 @@ jobs: - name: Setup Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: advisor/package-lock.json @@ -401,7 +401,7 @@ jobs: - name: Setup Node for trusted publisher uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" - name: Post PR review advisor link env: diff --git a/.github/workflows/pr-self-hosted.yaml b/.github/workflows/pr-self-hosted.yaml index be99af968cd..cc366fac328 100644 --- a/.github/workflows/pr-self-hosted.yaml +++ b/.github/workflows/pr-self-hosted.yaml @@ -107,7 +107,7 @@ jobs: if: ${{ steps.changed.outputs.selected == 'true' }} uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: 22 + node-version: ">=22.19.0 <23" - name: Install publication verifier dependencies if: ${{ steps.changed.outputs.selected == 'true' }} diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml index f7e1488c12e..2a916aebc75 100644 --- a/.github/workflows/pr.yaml +++ b/.github/workflows/pr.yaml @@ -63,7 +63,7 @@ jobs: - name: Setup Node.js for docs-only checks uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm - name: Install docs-only check dependencies @@ -159,7 +159,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm - name: Install dependencies @@ -479,7 +479,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "22" + node-version: ">=22.19.0 <23" cache: npm cache-dependency-path: | package-lock.json diff --git a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts index 8dd83d82603..1d2c03fbfe3 100644 --- a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts +++ b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts @@ -113,7 +113,7 @@ describe("hosted-runner recovery workflow boundary", () => { }); const setupNode = step(job, "Setup Node.js"); expect(setupNode.uses).toBe(TRUSTED_SETUP_NODE); - expect(setupNode.with).toEqual({ "node-version": "22" }); + expect(setupNode.with).toEqual({ "node-version": ">=22.19.0 <23" }); expect( job.steps?.filter((candidate) => candidate.uses?.startsWith("actions/checkout@")), ).toHaveLength(1); diff --git a/test/e2e/support/jetson-managed-revision-boundary.test.ts b/test/e2e/support/jetson-managed-revision-boundary.test.ts index 4d8db04a5ca..0ad80e02227 100644 --- a/test/e2e/support/jetson-managed-revision-boundary.test.ts +++ b/test/e2e/support/jetson-managed-revision-boundary.test.ts @@ -48,7 +48,7 @@ function syntheticJetsonWorkflow(selector = REQUIRED_SELECTOR): unknown { { name: "Set up Node for Jetson controller", uses: "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020", - with: { "node-version": 22 }, + with: { "node-version": ">=22.19.0 <23" }, }, { env: { diff --git a/tools/e2e/hermes-gpu-startup-workflow-boundary.mts b/tools/e2e/hermes-gpu-startup-workflow-boundary.mts index 737e54c7782..9b02ccedb0f 100644 --- a/tools/e2e/hermes-gpu-startup-workflow-boundary.mts +++ b/tools/e2e/hermes-gpu-startup-workflow-boundary.mts @@ -285,7 +285,7 @@ if ! @run restore`; ni !== restoreI + 1 || ni + 3 !== steps.indexOf(runStep) || node?.uses !== "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020" || - asRecord(node?.with)["node-version"] !== "22" || + asRecord(node?.with)["node-version"] !== ">=22.19.0 <23" || !trustedEnv(node) || asRecord(node?.env).NODE_OPTIONS !== "" || staleDockerRestore?.name !== "Recover Docker CLI before native Podman E2E" || diff --git a/tools/e2e/mcp-dev-workflow-boundary-digests.mts b/tools/e2e/mcp-dev-workflow-boundary-digests.mts index 89c39161f0b..3d715f33726 100644 --- a/tools/e2e/mcp-dev-workflow-boundary-digests.mts +++ b/tools/e2e/mcp-dev-workflow-boundary-digests.mts @@ -8,9 +8,9 @@ export const MCP_DEV_WORKFLOW_EXECUTION_CONTEXT_SHA256 = export const MCP_DEV_JOB_EXECUTION_CONTEXT_SHA256 = "9b70d22accbd7b413932e73b7e865097291af95eb3bacd4f862ff3f574325ab4"; export const MCP_DEV_TRUSTED_NODE_SETUP_CONTENT_SHA256 = - "504821ad93c57971d0281ef1130ed6008fadd331bd56acb1a6b5e6a3358f3e49"; + "d4a46db674c65bf14c80de6a9faa1702a0b6ff48781537871504e768cf222cf7"; export const MCP_DEV_TRUSTED_PREFIX_CONTENT_SHA256 = - "4c03445d26a30aabef34ab12879c95c01d5bc48ee1d192f588d47782935104cf"; + "31674eafe2ce79207c50cb2fb23f75ba0b2cdd572254f831754ca25beba82ac4"; export const MCP_DEV_POST_INSTALL_TRANSITION_CONTENT_SHA256 = "9fae24e2a586143abeb36916b556e924d268300d03375bfe6936c5ad97aab9d5"; diff --git a/tools/e2e/mcp-workflow-boundary.mts b/tools/e2e/mcp-workflow-boundary.mts index 3f549ca23f4..6b6fbd41300 100644 --- a/tools/e2e/mcp-workflow-boundary.mts +++ b/tools/e2e/mcp-workflow-boundary.mts @@ -795,7 +795,7 @@ function validateDevArtifactJob(errors: string[], job: UnknownRecord): void { if (!/^actions\/setup-node@[a-f0-9]{40}$/u.test(asString(setup.uses))) { errors.push(`${DEV_ARTIFACT_JOB} must use a SHA-pinned Node setup`); } - if (!hasExactEntries(asRecord(setup.with), { "node-version": 22 })) { + if (!hasExactEntries(asRecord(setup.with), { "node-version": ">=22.19.0 <23" })) { errors.push(`${DEV_ARTIFACT_JOB} must use only the reviewed Node version`); } const resolve = namedStep(job, "Resolve immutable OpenShell dev artifact"); diff --git a/tools/e2e/operations-workflow-boundary.mts b/tools/e2e/operations-workflow-boundary.mts index d51cc8ccce8..ce9f14b19de 100644 --- a/tools/e2e/operations-workflow-boundary.mts +++ b/tools/e2e/operations-workflow-boundary.mts @@ -757,7 +757,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): name: "Set up Node for publication verification", uses: "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020", with: { - "node-version": 22, + "node-version": ">=22.19.0 <23", }, }, { diff --git a/tools/e2e/workflow-boundary.mts b/tools/e2e/workflow-boundary.mts index 034fa234dbb..431c4b7b111 100644 --- a/tools/e2e/workflow-boundary.mts +++ b/tools/e2e/workflow-boundary.mts @@ -1985,8 +1985,8 @@ function validateJetsonControllerBoundary(errors: string[], jobs: WorkflowRecord errors.push("jetson-nvmap-gpu controller must set up Node.js"); } else { requireFullShaAction(errors, setupNode, "jetson-nvmap-gpu Node setup"); - if (asRecord(setupNode.with)["node-version"] !== 22) { - errors.push("jetson-nvmap-gpu controller must use Node.js 22"); + if (asRecord(setupNode.with)["node-version"] !== ">=22.19.0 <23") { + errors.push("jetson-nvmap-gpu controller must require Node.js 22.19 or later within 22.x"); } } const dispatch = namedStep(steps, "Dispatch exact commit to Jetson through operator backend"); @@ -2718,10 +2718,10 @@ function validateTrustedE2ePlannerBoundary( requireFullShaAction(errors, trustedPlannerSetup, "trusted E2E planner Node setup"); if ( !isDeepStrictEqual(asRecord(trustedPlannerSetup?.with), { - "node-version": 22, + "node-version": ">=22.19.0 <23", }) ) { - errors.push("trusted E2E planner must use Node 22"); + errors.push("trusted E2E planner must require Node.js 22.19 or later within 22.x"); } if (trustedPlannerInstall?.run !== "npm ci --ignore-scripts --no-audit --no-fund") { errors.push("trusted E2E planner dependencies must install without lifecycle scripts"); From bc37a4358800b0e4b70af6a8e0df481caf70da6e Mon Sep 17 00:00:00 2001 From: Carlos Villela Date: Wed, 9 Sep 2026 11:42:15 -0700 Subject: [PATCH 4/4] test: stop pinning Node selector text in workflow checks Signed-off-by: Carlos Villela --- .../hosted-runner-recovery-workflow.test.ts | 1 - ...mage-publication-workflow-boundary.test.ts | 2 +- .../mcp-workflow-compatibility.test.ts | 21 +++++++++++++++++++ .../shared-e2e-workflow-boundary.test.ts | 19 ++++++++++++++++- .../hermes-gpu-startup-workflow-boundary.mts | 1 - .../e2e/mcp-dev-workflow-boundary-digests.mts | 4 ++-- tools/e2e/mcp-workflow-boundary.mts | 18 ++++++++++++---- tools/e2e/operations-workflow-boundary.mts | 14 +++++++++---- tools/e2e/workflow-boundary.mts | 11 ++-------- 9 files changed, 68 insertions(+), 23 deletions(-) diff --git a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts index 1d2c03fbfe3..17bb004a752 100644 --- a/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts +++ b/test/automation/pull-requests/hosted-runner-recovery-workflow.test.ts @@ -113,7 +113,6 @@ describe("hosted-runner recovery workflow boundary", () => { }); const setupNode = step(job, "Setup Node.js"); expect(setupNode.uses).toBe(TRUSTED_SETUP_NODE); - expect(setupNode.with).toEqual({ "node-version": ">=22.19.0 <23" }); expect( job.steps?.filter((candidate) => candidate.uses?.startsWith("actions/checkout@")), ).toHaveLength(1); diff --git a/test/e2e/support/base-image-publication-workflow-boundary.test.ts b/test/e2e/support/base-image-publication-workflow-boundary.test.ts index df777e1ac3f..2763f9a6f88 100644 --- a/test/e2e/support/base-image-publication-workflow-boundary.test.ts +++ b/test/e2e/support/base-image-publication-workflow-boundary.test.ts @@ -205,7 +205,7 @@ describe("base-image publication workflow boundary (#7372)", () => { ["checkout credentials", (value) => (gateSteps(value)[1].with!["persist-credentials"] = true)], ["Node condition", (value) => (gateSteps(value)[2].if = "${{ always() }}")], ["Node pin", (value) => (gateSteps(value)[2].uses = "actions/setup-node@v6")], - ["Node version", (value) => (gateSteps(value)[2].with!["node-version"] = 20)], + ["Node dependency cache", (value) => (gateSteps(value)[2].with!.cache = "npm")], ["verifier condition", (value) => (gateSteps(value)[3].if = "${{ always() }}")], [ "base publication selection condition", diff --git a/test/e2e/support/mcp-workflow-compatibility.test.ts b/test/e2e/support/mcp-workflow-compatibility.test.ts index f14b1d97e2e..81791343dbb 100644 --- a/test/e2e/support/mcp-workflow-compatibility.test.ts +++ b/test/e2e/support/mcp-workflow-compatibility.test.ts @@ -12,6 +12,27 @@ import { validateMcpOpenShellWorkflowBoundary } from "../../../tools/e2e/mcp-wor import { requireFixture } from "./require-fixture"; describe("MCP workflow runtime compatibility", () => { + it.each([ + ["22.19.0", "openshell-dev-artifact"], + ["22.19.0", "mcp-bridge-dev"], + ["^22.19.0", "openshell-dev-artifact"], + ["^22.19.0", "mcp-bridge-dev"], + ])("accepts the compatible Node selector %s in %s", (version, jobName) => { + const directory = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-mcp-node-selector-")); + const workflowPath = path.join(directory, "e2e.yaml"); + try { + const workflow = YAML.parse(fs.readFileSync(".github/workflows/e2e.yaml", "utf8")); + const setup = workflow.jobs[jobName].steps.find((step: { uses?: string }) => + step.uses?.startsWith("actions/setup-node@"), + ); + setup.with["node-version"] = version; + fs.writeFileSync(workflowPath, YAML.stringify(workflow)); + expect(validateMcpOpenShellWorkflowBoundary(workflowPath)).toEqual([]); + } finally { + fs.rmSync(directory, { force: true, recursive: true }); + } + }); + it("accepts compatibility-step keys in any order (#6426)", () => { const directory = fs.mkdtempSync(path.join(os.tmpdir(), "nemoclaw-mcp-workflow-")); const workflowPath = path.join(directory, "e2e.yaml"); diff --git a/test/e2e/support/shared-e2e-workflow-boundary.test.ts b/test/e2e/support/shared-e2e-workflow-boundary.test.ts index 604785dbc61..c382a024102 100644 --- a/test/e2e/support/shared-e2e-workflow-boundary.test.ts +++ b/test/e2e/support/shared-e2e-workflow-boundary.test.ts @@ -22,7 +22,7 @@ type Workflow = { { env?: Record; needs?: string[]; - steps?: Array<{ name?: string; run?: string }>; + steps?: Array<{ name?: string; run?: string; with?: Record }>; } >; }; @@ -41,6 +41,23 @@ function validateMutatedWorkflow(mutator: (workflow: Workflow) => void): string[ } describe("shared E2E workflow boundary", () => { + it.each([ + ["22.19.0", "jetson-nvmap-gpu", "Set up Node for Jetson controller"], + ["22.19.0", "generate-matrix", "Set up Node for trusted E2E planning"], + ["22.19.0", "base-image-publication", "Set up Node for publication verification"], + ["22.19.0", "hermes-gpu-startup", "Reassert trusted Node runtime"], + ["^22.19.0", "jetson-nvmap-gpu", "Set up Node for Jetson controller"], + ["^22.19.0", "generate-matrix", "Set up Node for trusted E2E planning"], + ["^22.19.0", "base-image-publication", "Set up Node for publication verification"], + ["^22.19.0", "hermes-gpu-startup", "Reassert trusted Node runtime"], + ])("accepts the compatible Node selector %s in %s (%s)", (version, job, stepName) => { + const errors = validateMutatedWorkflow((workflow) => { + const step = workflow.jobs[job].steps!.find((candidate) => candidate.name === stepName)!; + step.with!["node-version"] = version; + }); + expect(errors).toEqual([]); + }); + it( "keeps every tagged credential-free test visible to Vitest discovery", testTimeoutOptions(15_000), diff --git a/tools/e2e/hermes-gpu-startup-workflow-boundary.mts b/tools/e2e/hermes-gpu-startup-workflow-boundary.mts index 9b02ccedb0f..35634256f18 100644 --- a/tools/e2e/hermes-gpu-startup-workflow-boundary.mts +++ b/tools/e2e/hermes-gpu-startup-workflow-boundary.mts @@ -285,7 +285,6 @@ if ! @run restore`; ni !== restoreI + 1 || ni + 3 !== steps.indexOf(runStep) || node?.uses !== "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020" || - asRecord(node?.with)["node-version"] !== ">=22.19.0 <23" || !trustedEnv(node) || asRecord(node?.env).NODE_OPTIONS !== "" || staleDockerRestore?.name !== "Recover Docker CLI before native Podman E2E" || diff --git a/tools/e2e/mcp-dev-workflow-boundary-digests.mts b/tools/e2e/mcp-dev-workflow-boundary-digests.mts index 3d715f33726..c44f9169d26 100644 --- a/tools/e2e/mcp-dev-workflow-boundary-digests.mts +++ b/tools/e2e/mcp-dev-workflow-boundary-digests.mts @@ -8,9 +8,9 @@ export const MCP_DEV_WORKFLOW_EXECUTION_CONTEXT_SHA256 = export const MCP_DEV_JOB_EXECUTION_CONTEXT_SHA256 = "9b70d22accbd7b413932e73b7e865097291af95eb3bacd4f862ff3f574325ab4"; export const MCP_DEV_TRUSTED_NODE_SETUP_CONTENT_SHA256 = - "d4a46db674c65bf14c80de6a9faa1702a0b6ff48781537871504e768cf222cf7"; + "69ce3f37667cc6b5301fbb76074d3575da1cd45eb90b164dc407a17137a2d273"; export const MCP_DEV_TRUSTED_PREFIX_CONTENT_SHA256 = - "31674eafe2ce79207c50cb2fb23f75ba0b2cdd572254f831754ca25beba82ac4"; + "13ef92da728304746efe1060102e392271a002e382d4ca540bcc38bbde838201"; export const MCP_DEV_POST_INSTALL_TRANSITION_CONTENT_SHA256 = "9fae24e2a586143abeb36916b556e924d268300d03375bfe6936c5ad97aab9d5"; diff --git a/tools/e2e/mcp-workflow-boundary.mts b/tools/e2e/mcp-workflow-boundary.mts index 6b6fbd41300..d8d9d215707 100644 --- a/tools/e2e/mcp-workflow-boundary.mts +++ b/tools/e2e/mcp-workflow-boundary.mts @@ -107,6 +107,11 @@ const FORBIDDEN_INFERENCE_SECRETS = type UnknownRecord = Record; +function nodeSetupSecurityBoundary(step: UnknownRecord): UnknownRecord { + const { "node-version": _nodeVersion, ...inputs } = asRecord(step.with); + return { ...step, with: inputs }; +} + function asRecord(value: unknown): UnknownRecord { return value !== null && typeof value === "object" && !Array.isArray(value) ? (value as UnknownRecord) @@ -345,7 +350,8 @@ function validateJobSecurity( const trustedNodeSetupIndex = steps.indexOf(trustedNodeSetup); if ( jobName === "mcp-bridge-dev" && - (contentSha256(trustedNodeSetup) !== MCP_DEV_TRUSTED_NODE_SETUP_CONTENT_SHA256 || + (contentSha256(nodeSetupSecurityBoundary(trustedNodeSetup)) !== + MCP_DEV_TRUSTED_NODE_SETUP_CONTENT_SHA256 || trustedNodeSetupIndex !== checkoutIndex - 1) ) { errors.push( @@ -593,7 +599,11 @@ function validateJobExecution( } if ( installIndex < 0 || - contentSha256(steps.slice(0, installIndex + 1)) !== MCP_DEV_TRUSTED_PREFIX_CONTENT_SHA256 + contentSha256( + steps + .slice(0, installIndex + 1) + .map((step) => (step === trustedNodeSetup ? nodeSetupSecurityBoundary(step) : step)), + ) !== MCP_DEV_TRUSTED_PREFIX_CONTENT_SHA256 ) { errors.push("mcp-bridge-dev must preserve every reviewed step through trusted installation"); } @@ -795,8 +805,8 @@ function validateDevArtifactJob(errors: string[], job: UnknownRecord): void { if (!/^actions\/setup-node@[a-f0-9]{40}$/u.test(asString(setup.uses))) { errors.push(`${DEV_ARTIFACT_JOB} must use a SHA-pinned Node setup`); } - if (!hasExactEntries(asRecord(setup.with), { "node-version": ">=22.19.0 <23" })) { - errors.push(`${DEV_ARTIFACT_JOB} must use only the reviewed Node version`); + if (Object.keys(asRecord(setup.with)).some((key) => key !== "node-version")) { + errors.push(`${DEV_ARTIFACT_JOB} must not enable additional Node setup inputs`); } const resolve = namedStep(job, "Resolve immutable OpenShell dev artifact"); requireEqual( diff --git a/tools/e2e/operations-workflow-boundary.mts b/tools/e2e/operations-workflow-boundary.mts index ce9f14b19de..c6052d59fe7 100644 --- a/tools/e2e/operations-workflow-boundary.mts +++ b/tools/e2e/operations-workflow-boundary.mts @@ -756,9 +756,7 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): { name: "Set up Node for publication verification", uses: "actions/setup-node@820762786026740c76f36085b0efc47a31fe5020", - with: { - "node-version": ">=22.19.0 <23", - }, + with: {}, }, { id: "select_pr_source", @@ -851,7 +849,15 @@ export function validateBaseImagePublicationGate(workflow: OperationsWorkflow): ], }; - if (!isDeepStrictEqual(job, expectedJob)) { + const securityBoundary = { + ...job, + steps: job.steps?.map((step) => { + if (step.name !== "Set up Node for publication verification") return step; + const { "node-version": _nodeVersion, ...inputs } = step.with ?? {}; + return { ...step, with: inputs }; + }), + }; + if (!isDeepStrictEqual(securityBoundary, expectedJob)) { errors.push( "base-image-publication job must preserve its exact trusted-mode classifier, minimal permissions, pinned checkout, and verifier boundary", ); diff --git a/tools/e2e/workflow-boundary.mts b/tools/e2e/workflow-boundary.mts index 431c4b7b111..732a1dbce33 100644 --- a/tools/e2e/workflow-boundary.mts +++ b/tools/e2e/workflow-boundary.mts @@ -1985,9 +1985,6 @@ function validateJetsonControllerBoundary(errors: string[], jobs: WorkflowRecord errors.push("jetson-nvmap-gpu controller must set up Node.js"); } else { requireFullShaAction(errors, setupNode, "jetson-nvmap-gpu Node setup"); - if (asRecord(setupNode.with)["node-version"] !== ">=22.19.0 <23") { - errors.push("jetson-nvmap-gpu controller must require Node.js 22.19 or later within 22.x"); - } } const dispatch = namedStep(steps, "Dispatch exact commit to Jetson through operator backend"); if ( @@ -2716,12 +2713,8 @@ function validateTrustedE2ePlannerBoundary( errors.push("trusted E2E planner checkout must use the workflow commit without credentials"); } requireFullShaAction(errors, trustedPlannerSetup, "trusted E2E planner Node setup"); - if ( - !isDeepStrictEqual(asRecord(trustedPlannerSetup?.with), { - "node-version": ">=22.19.0 <23", - }) - ) { - errors.push("trusted E2E planner must require Node.js 22.19 or later within 22.x"); + if (Object.keys(asRecord(trustedPlannerSetup?.with)).some((key) => key !== "node-version")) { + errors.push("trusted E2E planner must not enable additional Node setup inputs"); } if (trustedPlannerInstall?.run !== "npm ci --ignore-scripts --no-audit --no-fund") { errors.push("trusted E2E planner dependencies must install without lifecycle scripts");