diff --git a/AGENTS.md b/AGENTS.md index 5f715abc1b0..28d1b9cc2a6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -208,7 +208,10 @@ - Fresh Tahoe snapshot current reality: `brew` exists, `node` may not be on `PATH` in noninteractive guest exec. Use absolute `/opt/homebrew/bin/node` for repo/CLI runs when needed. - Preferred automation entrypoint: `pnpm test:parallels:macos`. It restores the snapshot most closely matching `macOS 26.3.1 fresh`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes. - Gateway verification in smoke runs should use `openclaw gateway status --deep --require-rpc`, not plain `--deep`, so probe failures go non-zero. + - Latest-release pre-upgrade diagnostics still need compatibility fallback: stable `2026.3.12` does not know `--require-rpc`, so precheck status dumps should fall back to plain `gateway status --deep` until the guest is upgraded. - Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-smoke.*`. + - All-OS parallel runs should share the host `dist` build via `/tmp/openclaw-parallels-build.lock` instead of rebuilding three times. + - Current expected outcome on latest stable pre-upgrade: `precheck=latest-ref-fail` is normal on `2026.3.12`; treat it as a baseline signal, not a regression, unless the post-upgrade `main` lane also fails. - Fresh host-served tgz install: restore fresh snapshot, install tgz as guest root with `HOME=/var/root`, then run onboarding as the desktop user via `prlctl exec --current-user`. - For `openclaw onboard --non-interactive --secret-input-mode ref --install-daemon`, expect env-backed auth-profile refs (for example `OPENAI_API_KEY`) to be copied into the service env at install time; this path was fixed and should stay green. - Don’t run local + gateway agent turns in parallel on the same fresh workspace/session; they can collide on the session lock. Run sequentially. @@ -216,10 +219,13 @@ - Parallels Windows smoke playbook: - Preferred automation entrypoint: `pnpm test:parallels:windows`. It restores the snapshot most closely matching `pre-openclaw-native-e2e-2026-03-12`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes. - Gateway verification in smoke runs should use `openclaw gateway status --deep --require-rpc`, not plain `--deep`, so probe failures go non-zero. + - Latest-release pre-upgrade diagnostics still need compatibility fallback: stable `2026.3.12` does not know `--require-rpc`, so precheck status dumps should fall back to plain `gateway status --deep` until the guest is upgraded. - Always use `prlctl exec --current-user` for Windows guest runs; plain `prlctl exec` lands in `NT AUTHORITY\SYSTEM` and does not match the real desktop-user install path. - Prefer explicit `npm.cmd` / `openclaw.cmd`. Bare `npm` / `openclaw` in PowerShell can hit the `.ps1` shim and fail under restrictive execution policy. - Use PowerShell only as the transport (`powershell.exe -NoProfile -ExecutionPolicy Bypass`) and call the `.cmd` shims explicitly from inside it. - Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-windows.*`. + - Current expected outcome on latest stable pre-upgrade: `precheck=latest-ref-fail` is normal on `2026.3.12`; treat it as a baseline signal, not a regression, unless the post-upgrade `main` lane also fails. + - Keep Windows onboarding/status text ASCII-clean in logs. Fancy punctuation in banners shows up as mojibake through the current guest PowerShell capture path. - Parallels Linux smoke playbook: - Preferred automation entrypoint: `pnpm test:parallels:linux`. It restores the snapshot most closely matching `fresh` on `Ubuntu 24.04.3 ARM64`, serves the current `main` tarball from the host, then runs fresh-install and latest-release-to-main smoke lanes. - Use plain `prlctl exec` on this snapshot. `--current-user` is not the right transport there. @@ -231,6 +237,7 @@ - When you do run Linux gateway checks manually from an interactive guest shell, use `openclaw gateway status --deep --require-rpc` so an RPC miss is a hard failure. - Prefer direct argv guest commands for fetch/install steps (`curl`, `npm install -g`, `openclaw ...`) over nested `bash -lc` quoting; Linux guest quoting through Parallels was the flaky part. - Harness output: pass `--json` for machine-readable summary; per-phase logs land under `/tmp/openclaw-parallels-linux.*`. + - Current expected outcome on Linux smoke: fresh + upgrade should pass installer and `agent --local`; gateway remains `skipped-no-detached-linux-gateway` on this snapshot and should not be treated as a regression by itself. - Never edit `node_modules` (global/Homebrew/npm/git installs too). Updates overwrite. Skill notes go in `tools.md` or `AGENTS.md`. - When adding a new `AGENTS.md` anywhere in the repo, also add a `CLAUDE.md` symlink pointing to it (example: `ln -s AGENTS.md CLAUDE.md`). - Signal: "update fly" => `fly ssh console -a flawd-bot -C "bash -lc 'cd /data/clawd/openclaw && git pull --rebase origin main'"` then `fly machines restart e825232f34d058 -a flawd-bot`. diff --git a/scripts/e2e/parallels-linux-smoke.sh b/scripts/e2e/parallels-linux-smoke.sh index 120a8290bc2..dfed00bf89d 100644 --- a/scripts/e2e/parallels-linux-smoke.sh +++ b/scripts/e2e/parallels-linux-smoke.sh @@ -17,6 +17,7 @@ MAIN_TGZ_DIR="$(mktemp -d)" MAIN_TGZ_PATH="" SERVER_PID="" RUN_DIR="$(mktemp -d /tmp/openclaw-parallels-linux.XXXXXX)" +BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock" TIMEOUT_SNAPSHOT_S=180 TIMEOUT_BOOTSTRAP_S=600 @@ -260,16 +261,41 @@ else: PY } +acquire_build_lock() { + local owner_pid="" + while ! mkdir "$BUILD_LOCK_DIR" 2>/dev/null; do + if [[ -f "$BUILD_LOCK_DIR/pid" ]]; then + owner_pid="$(cat "$BUILD_LOCK_DIR/pid" 2>/dev/null || true)" + if [[ -n "$owner_pid" ]] && ! kill -0 "$owner_pid" >/dev/null 2>&1; then + warn "Removing stale Parallels build lock" + rm -rf "$BUILD_LOCK_DIR" + continue + fi + fi + sleep 1 + done + printf '%s\n' "$$" >"$BUILD_LOCK_DIR/pid" +} + +release_build_lock() { + if [[ -d "$BUILD_LOCK_DIR" ]]; then + rm -rf "$BUILD_LOCK_DIR" + fi +} + ensure_current_build() { local head build_commit + acquire_build_lock head="$(git rev-parse HEAD)" build_commit="$(current_build_commit)" if [[ "$build_commit" == "$head" ]]; then + release_build_lock return fi say "Build dist for current head" pnpm build build_commit="$(current_build_commit)" + release_build_lock [[ "$build_commit" == "$head" ]] || die "dist/build-info.json still does not match HEAD after build" } diff --git a/scripts/e2e/parallels-macos-smoke.sh b/scripts/e2e/parallels-macos-smoke.sh index c85f3d237ec..4de2fb19ae3 100644 --- a/scripts/e2e/parallels-macos-smoke.sh +++ b/scripts/e2e/parallels-macos-smoke.sh @@ -24,6 +24,7 @@ MAIN_TGZ_DIR="$(mktemp -d)" MAIN_TGZ_PATH="" SERVER_PID="" RUN_DIR="$(mktemp -d /tmp/openclaw-parallels-smoke.XXXXXX)" +BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock" TIMEOUT_INSTALL_S=900 TIMEOUT_VERIFY_S=60 @@ -397,16 +398,41 @@ else: PY } +acquire_build_lock() { + local owner_pid="" + while ! mkdir "$BUILD_LOCK_DIR" 2>/dev/null; do + if [[ -f "$BUILD_LOCK_DIR/pid" ]]; then + owner_pid="$(cat "$BUILD_LOCK_DIR/pid" 2>/dev/null || true)" + if [[ -n "$owner_pid" ]] && ! kill -0 "$owner_pid" >/dev/null 2>&1; then + warn "Removing stale Parallels build lock" + rm -rf "$BUILD_LOCK_DIR" + continue + fi + fi + sleep 1 + done + printf '%s\n' "$$" >"$BUILD_LOCK_DIR/pid" +} + +release_build_lock() { + if [[ -d "$BUILD_LOCK_DIR" ]]; then + rm -rf "$BUILD_LOCK_DIR" + fi +} + ensure_current_build() { local head build_commit + acquire_build_lock head="$(git rev-parse HEAD)" build_commit="$(current_build_commit)" if [[ "$build_commit" == "$head" ]]; then + release_build_lock return fi say "Build dist for current head" pnpm build build_commit="$(current_build_commit)" + release_build_lock [[ "$build_commit" == "$head" ]] || die "dist/build-info.json still does not match HEAD after build" } @@ -465,6 +491,14 @@ verify_gateway() { guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" gateway status --deep --require-rpc } +show_gateway_status_compat() { + if guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" gateway status --help | grep -Fq -- "--require-rpc"; then + guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" gateway status --deep --require-rpc + return + fi + guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" gateway status --deep +} + verify_turn() { guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" agent --agent main --message ping --json } @@ -587,7 +621,7 @@ capture_latest_ref_failure() { fi warn "Latest release ref-mode onboard failed pre-upgrade" set +e - guest_current_user_exec "$GUEST_NODE_BIN" "$GUEST_OPENCLAW_ENTRY" gateway status --deep --require-rpc || true + show_gateway_status_compat || true set -e return 1 } diff --git a/scripts/e2e/parallels-windows-smoke.sh b/scripts/e2e/parallels-windows-smoke.sh index 548d3d033aa..3b9ec366790 100644 --- a/scripts/e2e/parallels-windows-smoke.sh +++ b/scripts/e2e/parallels-windows-smoke.sh @@ -20,6 +20,7 @@ MINGIT_ZIP_PATH="" MINGIT_ZIP_NAME="" SERVER_PID="" RUN_DIR="$(mktemp -d /tmp/openclaw-parallels-windows.XXXXXX)" +BUILD_LOCK_DIR="${TMPDIR:-/tmp}/openclaw-parallels-build.lock" TIMEOUT_SNAPSHOT_S=240 TIMEOUT_INSTALL_S=1200 @@ -509,16 +510,41 @@ else: PY } +acquire_build_lock() { + local owner_pid="" + while ! mkdir "$BUILD_LOCK_DIR" 2>/dev/null; do + if [[ -f "$BUILD_LOCK_DIR/pid" ]]; then + owner_pid="$(cat "$BUILD_LOCK_DIR/pid" 2>/dev/null || true)" + if [[ -n "$owner_pid" ]] && ! kill -0 "$owner_pid" >/dev/null 2>&1; then + warn "Removing stale Parallels build lock" + rm -rf "$BUILD_LOCK_DIR" + continue + fi + fi + sleep 1 + done + printf '%s\n' "$$" >"$BUILD_LOCK_DIR/pid" +} + +release_build_lock() { + if [[ -d "$BUILD_LOCK_DIR" ]]; then + rm -rf "$BUILD_LOCK_DIR" + fi +} + ensure_current_build() { local head build_commit + acquire_build_lock head="$(git rev-parse HEAD)" build_commit="$(current_build_commit)" if [[ "$build_commit" == "$head" ]]; then + release_build_lock return fi say "Build dist for current head" pnpm build build_commit="$(current_build_commit)" + release_build_lock [[ "$build_commit" == "$head" ]] || die "dist/build-info.json still does not match HEAD after build" } @@ -678,6 +704,14 @@ verify_gateway() { guest_run_openclaw "" "" gateway status --deep --require-rpc } +show_gateway_status_compat() { + if guest_run_openclaw "" "" gateway status --help | grep -Fq -- "--require-rpc"; then + guest_run_openclaw "" "" gateway status --deep --require-rpc + return + fi + guest_run_openclaw "" "" gateway status --deep +} + verify_turn() { guest_run_openclaw "" "" agent --agent main --message ping --json } @@ -693,7 +727,7 @@ capture_latest_ref_failure() { fi warn "Latest release ref-mode onboard failed pre-upgrade" set +e - verify_gateway || true + show_gateway_status_compat || true set -e return 1 }