Skip to content

fix: improve npm install resilience on low-memory systems#39463

Closed
NewdlDewdl wants to merge 6 commits into
openclaw:mainfrom
NewdlDewdl:fix/issue-39447-npm-install-oom
Closed

fix: improve npm install resilience on low-memory systems#39463
NewdlDewdl wants to merge 6 commits into
openclaw:mainfrom
NewdlDewdl:fix/issue-39447-npm-install-oom

Conversation

@NewdlDewdl

Copy link
Copy Markdown
Contributor

Fixes #39447

Problem

npm install fails with "Killed" on low-memory VPS instances (e.g., DigitalOcean droplets with <2GB RAM):

  • SHARP_IGNORE_GLOBAL_LIBVIPS=1 forced sharp to build from source
  • Sharp builds require ~2GB+ RAM, exceeding small droplet capacity
  • OOM killer terminates the process with no clear error message
  • No memory detection or mitigation strategy

Solution

1. Prefer prebuilt sharp binaries (memory-efficient)

  • Changed SHARP_IGNORE_GLOBAL_LIBVIPS default from 1 to 0
  • Uses prebuilt binaries instead of compiling from source
  • Dramatically reduces memory requirements during npm install
  • Users can still force source builds with SHARP_IGNORE_GLOBAL_LIBVIPS=1

2. Memory detection and swap file creation

  • get_available_memory_mb(): detects available RAM on Linux/macOS
  • setup_low_memory_environment(): auto-creates 2GB swap on systems with <2GB RAM
  • create_swap_file(): creates /swapfile-openclaw with proper permissions
  • Runs proactively before npm install attempt

3. OOM detection and recovery

  • npm_log_indicates_oom_killed(): detects when npm was killed by OOM
  • Enhanced retry logic: creates swap and retries npm install after OOM
  • Clear error messages with memory stats and manual recovery steps
  • Actionable guidance when auto-swap creation fails

Testing

  • ✅ Full quality gate passed (build, lint, format, tests)
  • ✅ All existing error recovery paths preserved
  • ✅ Backward compatible: existing installs unaffected

Impact

Makes OpenClaw installable on DigitalOcean's smallest droplets and other low-memory VPS instances without manual swap configuration.


Ref: #39447

@openclaw-barnacle openclaw-barnacle Bot added scripts Repository scripts size: S labels Mar 8, 2026
@alvinttang

Copy link
Copy Markdown
Contributor

Good approach! Handling OOM issues during npm install is important for production deployments. 👍

@greptile-apps

greptile-apps Bot commented Mar 8, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves resilience of scripts/install.sh on low-memory VPS instances by proactively detecting available RAM, creating a 2 GB swap file when memory is insufficient, and adding an OOM-kill recovery path that retries npm install after swap creation. It also changes the SHARP_IGNORE_GLOBAL_LIBVIPS default from 1 to 0 to prefer prebuilt binaries over expensive source builds.

Two logic bugs were identified in the new code:

  • Unreliable OOM detection: npm_log_indicates_oom_killed uses log file size (< 100 bytes) as a proxy for OOM kills. This will both miss OOM kills that produced larger logs and trigger false positives for many unrelated npm failures (network errors, permission errors, etc.). Checking for the literal Killed string printed by the kernel or the SIGKILL signal in npm output is far more reliable.
  • Wrong /proc/meminfo field in has_sufficient_swap: The function reads SwapTotal (total swap capacity) instead of SwapFree (currently available swap). On a system with exhausted swap, this incorrectly reports that sufficient swap exists, causing the retry path to skip swap creation and instead tell the user to upgrade their droplet.

Confidence Score: 2/5

  • Two logic bugs in critical OOM/swap handling code that will cause incorrect behavior on affected systems
  • The PR contains two concrete logic bugs: (1) the OOM detection heuristic (checking log file size < 100 bytes) is unreliable and will produce both false positives on non-OOM failures and false negatives on OOM events with larger logs, causing unnecessary or missed swap creation; (2) has_sufficient_swap checks SwapTotal instead of SwapFree, causing it to incorrectly skip swap creation on systems with exhausted swap, where swap creation would actually help. These bugs directly undermine the core reliability improvements the PR aims to deliver for low-memory systems.
  • scripts/install.sh — specifically the npm_log_indicates_oom_killed function (lines 749–759) and the has_sufficient_swap function (lines 692–699)

Last reviewed commit: 83ef500

Comment thread scripts/install.sh Outdated
Comment on lines +749 to +759
npm_log_indicates_oom_killed() {
local log="$1"
# Check if the process was killed (exit code 137 = SIGKILL, often OOM)
# The install.sh script will show "Killed" in the error output
if [[ ! -f "$log" ]]; then
return 1
fi
# Empty or very small log files often indicate OOM kill
local log_size
log_size="$(wc -c < "$log" 2>/dev/null || echo "0")"
[[ "$log_size" -lt 100 ]]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unreliable OOM detection heuristic

The function assumes any failed log file under 100 bytes means the process was OOM-killed. This is a very weak signal that will produce false positives for many other npm failure modes (e.g., network errors, permission errors, or a very fast failure). An OOM-killed process that had already written substantial output to the log would also be missed.

A more reliable approach is to check for the literal "Killed" string in the log output (which the Linux kernel prints to stderr when a process is SIGKILL'd), or to capture and inspect the actual exit code of the npm command.

Suggested change
npm_log_indicates_oom_killed() {
local log="$1"
# Check if the process was killed (exit code 137 = SIGKILL, often OOM)
# The install.sh script will show "Killed" in the error output
if [[ ! -f "$log" ]]; then
return 1
fi
# Empty or very small log files often indicate OOM kill
local log_size
log_size="$(wc -c < "$log" 2>/dev/null || echo "0")"
[[ "$log_size" -lt 100 ]]
npm_log_indicates_oom_killed() {
local log="$1"
if [[ ! -f "$log" ]]; then
return 1
fi
# "Killed" is printed by the shell/kernel when a process receives SIGKILL (exit 137)
grep -qE '^Killed$|^Killed |npm ERR! signal SIGKILL' "$log" 2>/dev/null
}
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/install.sh
Line: 749-759

Comment:
**Unreliable OOM detection heuristic**

The function assumes any failed log file under 100 bytes means the process was OOM-killed. This is a very weak signal that will produce false positives for many other npm failure modes (e.g., network errors, permission errors, or a very fast failure). An OOM-killed process that had already written substantial output to the log would also be missed.

A more reliable approach is to check for the literal "Killed" string in the log output (which the Linux kernel prints to stderr when a process is SIGKILL'd), or to capture and inspect the actual exit code of the npm command.

```suggestion
npm_log_indicates_oom_killed() {
    local log="$1"
    if [[ ! -f "$log" ]]; then
        return 1
    fi
    # "Killed" is printed by the shell/kernel when a process receives SIGKILL (exit 137)
    grep -qE '^Killed$|^Killed |npm ERR! signal SIGKILL' "$log" 2>/dev/null
}
```

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 8ab82a8: removed the tiny-log-size heuristic and switched OOM detection to explicit signals only (captured npm exit code 137 + SIGKILL/'Killed'/OOM markers in output).

Comment thread scripts/install.sh Outdated
Comment on lines +696 to +698
local swap_total_kb
swap_total_kb="$(awk '/SwapTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")"
[[ "$swap_total_kb" -ge 1048576 ]] # At least 1GB swap

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SwapTotal checked instead of SwapFree

SwapTotal is the total swap partition/file size, which is non-zero even when all swap space is currently exhausted. On a system where 1 GB of swap exists but is 100% in use, this function returns true (sufficient swap), and the OOM retry path falls into the else branch telling the user to upgrade their droplet — even though creating additional swap would actually help.

SwapFree (free/available swap) is the correct field to check here.

Suggested change
local swap_total_kb
swap_total_kb="$(awk '/SwapTotal/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")"
[[ "$swap_total_kb" -ge 1048576 ]] # At least 1GB swap
swap_total_kb="$(awk '/SwapFree/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")"
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/install.sh
Line: 696-698

Comment:
**`SwapTotal` checked instead of `SwapFree`**

`SwapTotal` is the total swap partition/file size, which is non-zero even when all swap space is currently exhausted. On a system where 1 GB of swap exists but is 100% in use, this function returns `true` (sufficient swap), and the OOM retry path falls into the `else` branch telling the user to upgrade their droplet — even though creating additional swap would actually help.

`SwapFree` (free/available swap) is the correct field to check here.

```suggestion
    swap_total_kb="$(awk '/SwapFree/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")"
```

How can I resolve this? If you propose a fix, please make it concise.

@0xsline 0xsline Mar 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch - fixed in 8ab82a8. has_sufficient_swap now checks SwapFree (available swap) instead of SwapTotal, so exhausted swap no longer gets treated as sufficient.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 83ef500744

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/install.sh Outdated
GIT_DIR=${OPENCLAW_GIT_DIR:-$GIT_DIR_DEFAULT}
GIT_UPDATE=${OPENCLAW_GIT_UPDATE:-1}
SHARP_IGNORE_GLOBAL_LIBVIPS="${SHARP_IGNORE_GLOBAL_LIBVIPS:-1}"
SHARP_IGNORE_GLOBAL_LIBVIPS="${SHARP_IGNORE_GLOBAL_LIBVIPS:-0}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore SHARP_IGNORE_GLOBAL_LIBVIPS default to 1

This default flip likely inverts the intended sharp behavior: SHARP_IGNORE_GLOBAL_LIBVIPS=1 is documented in this repo as the way to avoid native libvips builds and use prebuilt binaries (see docs/install/index.md and docs/install/installer.md), but setting the installer default to 0 makes installs prefer the global libvips path again when present. On machines with global libvips (a common macOS/Homebrew setup), this can reintroduce source builds and the same OOM/install instability this change is trying to fix.

Useful? React with 👍 / 👎.

@0xsline 0xsline Mar 8, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 8ab82a8: restored installer default to SHARP_IGNORE_GLOBAL_LIBVIPS=1 and aligned the help text accordingly.

Comment thread scripts/install.sh Outdated
# Empty or very small log files often indicate OOM kill
local log_size
log_size="$(wc -c < "$log" 2>/dev/null || echo "0")"
[[ "$log_size" -lt 100 ]]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use explicit OOM signals instead of tiny-log heuristic

Classifying OOM solely by log_size < 100 creates false positives for non-OOM npm failures that emit short output (for example early shell/env/npm invocation errors). Because install_openclaw_npm treats this as definitive OOM and returns after memory advice, it skips normal recovery/diagnostic paths and can mislead users on healthy-memory systems; detection should key off explicit OOM indicators (like Killed/exit 137) rather than log length alone.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 8ab82a8. OOM detection now keys off explicit signals (exit 137 and SIGKILL/Killed/OOM indicators), not log length, so non-OOM short failures still follow normal diagnostics/recovery.

0xsline pushed a commit to 0xsline/openclaw that referenced this pull request Mar 8, 2026
@0xsline

0xsline commented Mar 8, 2026

Copy link
Copy Markdown

Addressed review feedback in 8ab82a8 for the OOM/swap logic:\n\n- Replaced tiny-log heuristic with explicit OOM signals (exit 137 plus SIGKILL/Killed/OOM markers).\n- Updated swap sufficiency check to use SwapFree instead of SwapTotal.\n- Restored installer default SHARP_IGNORE_GLOBAL_LIBVIPS=1 and updated usage text to match.\n\nNote: I could not push to the original PR head branch due permission denial (403), so this commit is available on my fork branch 0xsline:fix/issue-39447-npm-install-oom.

@aisle-research-bot

aisle-research-bot Bot commented Mar 11, 2026

Copy link
Copy Markdown

🔒 Aisle Security Analysis

We found 2 potential security issue(s) in this PR:

# Severity Title
1 🟠 High Swapfile created with potentially permissive permissions before chmod (permission-race info disclosure)
2 🟡 Medium Installer creates and enables persistent unencrypted swap file without user opt-in
1. 🟠 Swapfile created with potentially permissive permissions before chmod (permission-race info disclosure)
Property Value
Severity High
CWE CWE-732
Location scripts/install.sh:775-780

Description

The installer creates and enables a system swap file (/swapfile-openclaw) as root via dd, then changes permissions to 0600 only afterwards.

On typical systems with umask 022, dd will create the file as 0644 (or otherwise more permissive than 0600) until the later chmod runs. This introduces a race window where a local unprivileged user could open the swapfile for reading before permissions are tightened, and keep the file descriptor open.

Because swap files can later contain paged-out memory (potentially including secrets), this can lead to sensitive information disclosure even after chmod 600 is applied (permission checks occur at open time, not continuously).

Vulnerable code:

maybe_sudo dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" oflag=excl status=none 2>/dev/null || return 1
maybe_sudo chmod 600 "$swap_file" || return 1
maybe_sudo mkswap "$swap_file" >/dev/null 2>&1 || return 1
maybe_sudo swapon "$swap_file" || return 1

Recommendation

Ensure the swapfile is created with restrictive permissions from the first moment it exists.

Options:

  1. Set a restrictive umask for just the creation step:
create_swap_file() {
  ...
  maybe_sudo bash -c 'umask 077 && dd if=/dev/zero of="$1" bs=1M count="$2" oflag=excl status=none' _ "$swap_file" "$swap_size_mb" || return 1
  maybe_sudo chmod 600 "$swap_file" || return 1
  ...
}
  1. Prefer a create-and-set-mode primitive (e.g., install) before writing:
maybe_sudo install -m 600 /dev/null "$swap_file" || return 1
maybe_sudo dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" conv=notrunc status=none || return 1

Also consider using swapoff/cleanup on failure paths to avoid leaving a partially-created swapfile around.

2. 🟡 Installer creates and enables persistent unencrypted swap file without user opt-in
Property Value
Severity Medium
CWE CWE-312
Location scripts/install.sh:743-783

Description

The installer adds automatic swap provisioning on Linux by creating /swapfile-openclaw (2GB) and enabling it via swapon when available RAM is low.

Security/privacy/system-integrity concerns:

  • No explicit user consent/opt-in: swap creation is triggered automatically in setup_low_memory_environment before npm install.
  • Persistent system modification: the script enables swap (swapon) but does not swapoff or remove the swap file on exit/success/failure. This can leave swap enabled beyond installation.
  • Potential sensitive data exposure: swap is written to disk and may contain sensitive material (tokens, env vars, message contents) and is not encrypted/configured securely by this script.
  • Local resource/availability impact: creates a 2GB file on / which can surprise users and may contribute to disk pressure/DoS on small or multi-tenant systems.

Vulnerable code:

local swap_file="/swapfile-openclaw"
local swap_size_mb=2048
...
maybe_sudo dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" oflag=excl ...
...
maybe_sudo mkswap "$swap_file"
maybe_sudo swapon "$swap_file"

Recommendation

Require explicit user opt-in and ensure cleanup.

Safer approach:

  1. Ask for confirmation (or require an environment flag like OPENCLAW_ALLOW_SWAP=1).
  2. Track whether the installer created/enabled swap, and always clean up via trap on EXIT (both success and failure).
  3. If swap must persist, clearly document it and optionally integrate with the OS's swap management (e.g., /etc/fstab) and recommend encrypted swap where available.

Example implementation:

OPENCLAW_SWAP_FILE="/swapfile-openclaw"
OPENCLAW_SWAP_CREATED=0

cleanup_openclaw_swap() {
  if [[ "$OPENCLAW_SWAP_CREATED" -eq 1 ]]; then
    maybe_sudo swapoff "$OPENCLAW_SWAP_FILE" 2>/dev/null || true
    maybe_sudo rm -f "$OPENCLAW_SWAP_FILE" 2>/dev/null || true
  fi
}
trap cleanup_openclaw_swap EXIT

create_swap_file() {
  [[ "${OPENCLAW_ALLOW_SWAP:-0}" == "1" ]] || return 1
  ...
  maybe_sudo swapon "$OPENCLAW_SWAP_FILE" || return 1
  OPENCLAW_SWAP_CREATED=1
}

Analyzed PR: #39463 at commit bbde415

Last updated on: 2026-04-22T07:28:10Z

@NewdlDewdl

Copy link
Copy Markdown
Contributor Author

Addressed the OOM/swap review feedback in 193085366f923ef268d7d3f498cd0be9ac07846d and pushed to this PR branch.\n\nChanges:\n- OOM detection now checks explicit signals (exit 137, SIGKILL/Killed/OOM markers) instead of tiny-log heuristics.\n- Swap sufficiency on Linux now uses SwapFree (available swap) instead of SwapTotal.\n- Restored installer default SHARP_IGNORE_GLOBAL_LIBVIPS=1 and aligned usage text.\n\nValidation:\n- Ran full quality gate on the branch (install/build/format:check/tsgo/lint/test): PASS.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 193085366f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/install.sh Outdated
return 1
fi

require_sudo

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Avoid hard-exiting when swap setup lacks sudo

install_openclaw_npm treats low-memory preparation as best-effort (setup_low_memory_environment || true), but this path can still terminate the whole installer because create_swap_file invokes require_sudo, which calls exit 1 if sudo is missing. On low-memory Linux systems running as non-root without sudo (common in minimal/container images), the installer now aborts before attempting npm install, even when a user-local npm prefix would otherwise work. This should return a failure status instead of exiting so normal install/recovery logic can continue.

Useful? React with 👍 / 👎.

@NewdlDewdl

Copy link
Copy Markdown
Contributor Author

Addressed the latest review feedback in 99b84ad2b and pushed to this PR branch.

What changed:

  • Avoid hard exit in swap setup on low-memory Linux hosts without sudo; swap setup now degrades gracefully and installer continues with diagnostics/recovery paths.
  • Harden automatic swap creation with safety checks (existing/active swapfile detection, symlink rejection, disk headroom check, and exclusive file creation).
  • Keep manual swap workaround guidance when automatic setup is unavailable.

Validation:

  • Ran full quality gate on this branch: PASS (pnpm install, build, format:check, tsgo, lint, test).

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 99b84ad2b3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/install.sh
Comment on lines +776 to +779
maybe_sudo dd if=/dev/zero of="$swap_file" bs=1M count="$swap_size_mb" oflag=excl status=none 2>/dev/null || return 1
maybe_sudo chmod 600 "$swap_file" || return 1
maybe_sudo mkswap "$swap_file" >/dev/null 2>&1 || return 1
maybe_sudo swapon "$swap_file" || return 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clean up partial swap file after swapon failure

If dd/mkswap succeed but swapon fails (a common case in containers or restricted VMs without CAP_SYS_ADMIN), this function returns immediately and leaves /swapfile-openclaw on disk. Subsequent installer runs then hit the existing-file guard and skip automatic swap setup forever, while still consuming ~2GB of disk, so the recovery path introduced here can get stuck until the user manually removes the file.

Useful? React with 👍 / 👎.

Comment thread scripts/install.sh
Comment on lines +679 to +680
avail_kb="$(awk '/MemAvailable/ {print $2}' /proc/meminfo 2>/dev/null || echo "0")"
echo $((avail_kb / 1024))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Detect low memory from cgroup limits, not only /proc/meminfo

get_available_memory_mb uses /proc/meminfo MemAvailable, which often reports host memory rather than the container’s cgroup limit. On memory-limited containers this can overreport available RAM, causing the installer to skip swap setup and then treat an OOM-killed install as a hard failure instead of attempting the swap retry path. Reading cgroup memory limits when present would avoid this false “enough memory” classification.

Useful? React with 👍 / 👎.

@NewdlDewdl

Copy link
Copy Markdown
Contributor Author

Contributor cycle check-in: CI is currently red on this PR, and automation cannot rerun the failed workflow because this account lacks repository admin rerun permissions (GitHub returned: 'Must have admin rights to Repository'). No code changes were pushed in this cycle. If maintainers want this PR kept active, please rerun CI from the repo side and I can follow up with fixes from the resulting failures.

@NewdlDewdl
NewdlDewdl force-pushed the fix/issue-39447-npm-install-oom branch from 99b84ad to 2d609e0 Compare March 15, 2026 09:20

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d609e048f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/install.sh Outdated
fi

# Look for explicit OOM/SIGKILL indicators from shell/npm output.
grep -Eiq '(^|[[:space:]])Killed($|[[:space:]])|npm (ERR!|error) signal SIGKILL|signal SIGKILL|out of memory|oom' "$log" 2>/dev/null

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restrict OOM log matching to explicit tokens

The new OOM detector matches any occurrence of oom anywhere in the npm log, so unrelated strings like room or package names such as sonic-boom satisfy this check. When that happens on normal-memory hosts (available_mb >= 2048), install_openclaw_npm takes the OOM path and returns early with memory advice, skipping the normal build-tool remediation and detailed npm diagnostics for the real failure cause. Please tighten this regex to word-bounded OOM indicators (or specific npm signal lines) so non-OOM failures are not misclassified.

Useful? React with 👍 / 👎.

@NewdlDewdl

Copy link
Copy Markdown
Contributor Author

Addressed the Codex review note about broad OOM matching.

Change made

  • Tightened npm_log_indicates_oom_killed regex in scripts/install.sh to require oom as a standalone token boundary ((^|[^[:alnum:]_])oom([^[:alnum:]_]|$)), so unrelated substrings (for example room) no longer match.

Verification run locally

  • scripts/quality_gate.sh /Users/newdldewdl/openclaw-contrib-pr39463
    • pnpm install
    • pnpm build
    • pnpm format:check
    • pnpm tsgo
    • pnpm lint
    • pnpm test ❌ failed in existing src/tts/tts.test.ts mock export coverage (resolveModelAsync missing on mock), unrelated to scripts/install.sh.

I pushed the fix commit to this PR branch for CI re-evaluation.

@openclaw-barnacle openclaw-barnacle Bot added the channel: telegram Channel integration: telegram label Apr 1, 2026
Addresses openclaw#39447 - npm install killed on Ubuntu 24.04 droplet

Problem:
- npm install process killed (OOM) on low-memory VPS instances
- SHARP_IGNORE_GLOBAL_LIBVIPS=1 forced sharp build from source
- Sharp builds are extremely memory-intensive (requires ~2GB+ RAM)
- No memory detection or swap mitigation

Solution:
1. Change SHARP_IGNORE_GLOBAL_LIBVIPS default from 1 to 0
   - Prefers prebuilt sharp binaries (much faster, less memory)
   - Only builds from source when env var explicitly set to 1

2. Add memory detection and swap file creation:
   - Detects available memory on Linux and macOS
   - Auto-creates 2GB swap file on low-memory Linux systems
   - Runs setup_low_memory_environment() before npm install

3. Detect and handle OOM/Killed scenarios:
   - npm_log_indicates_oom_killed() detects empty/killed logs
   - Provides actionable error messages with memory info
   - Suggests manual swap creation steps if auto-setup fails

4. Enhanced retry logic:
   - Retries npm install after swap creation
   - Clear status messages for swap/build-tool fix attempts
   - Better error diagnostics for memory-related failures

This change makes OpenClaw installable on DigitalOcean's smallest
droplets and other low-memory VPS instances, while maintaining the
option to build from source when needed.

Ref: openclaw#39447
@NewdlDewdl
NewdlDewdl force-pushed the fix/issue-39447-npm-install-oom branch from 7fa09e0 to 077e6f6 Compare April 22, 2026 07:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 077e6f656a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 66 to 70
route = {
...route,
agentId: topicAgentId,
sessionKey: buildAgentSessionKey({
agentId: topicAgentId,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Keep sessionKey binding before deriving topic route policy

This change removes the local sessionKey binding in the topic override block, but the code below still uses sessionKey to compute lastRoutePolicy. When topicAgentId is set, that branch now hits ReferenceError: sessionKey is not defined, which breaks Telegram topic-bound routing instead of preserving the configured topic session.

Useful? React with 👍 / 👎.

Comment on lines +15 to +18
DEFAULT_ACCOUNT_ID,
resolveAgentIdFromSessionKey,
sanitizeAgentId,
} from "openclaw/plugin-sdk/routing";
import { logVerbose } from "openclaw/plugin-sdk/runtime-env";
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
} from "../../../src/routing/session-key.js";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore helper imports still referenced in conversation routing

The import rewrite drops the logVerbose and normalizeLowercaseStringOrEmpty imports, but both identifiers are still referenced later in this module (resolveTelegramConversationRoute and resolveTelegramConversationBaseSessionKey). That leaves unresolved bindings in runtime code paths and prevents this route module from executing correctly.

Useful? React with 👍 / 👎.

@openclaw-barnacle openclaw-barnacle Bot removed the channel: telegram Channel integration: telegram label Apr 22, 2026
@NewdlDewdl

Copy link
Copy Markdown
Contributor Author

Contributor cycle follow-up:\n\nI reviewed the new Codex/Aisle feedback first. The two Codex P1 thread comments were against commit ; current PR head already has both fixes in :\n- is restored before \n- and imports are present\n\nI also ran the full quality gate before attempting any further push. Baseline is currently red on (,

[email protected] test /Users/newdldewdl/openclaw-contrib
node scripts/test-parallel.mjs

[test-parallel] start unit-fast-batch-1 workers=2 filters=all
[test-parallel] start unit-fast-batch-2 workers=2 filters=all
[test-parallel] start unit-fast-batch-3 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cli/daemon-cli/response.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/message-capability-matrix.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/directory-cli.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/acp-bindings.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 412�[2mms�[22m�[39m
�[32m✓�[39m src/channels/status-reactions.test.ts �[2m(�[22m�[2m37 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/cli/channel-auth.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cli/config-cli.test.ts �[2m(�[22m�[2m49 tests�[22m�[2m)�[22m�[33m 436�[2mms�[22m�[39m
�[32m✓�[39m src/channels/status-reactions.slack-lifecycle.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/account-action-gate.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/gateway-token-drift.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/transport/stall-watchdog.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/acp/persistent-bindings.test.ts �[2m(�[22m�[2m29 tests�[22m�[2m)�[22m�[33m 1855�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/outbound/direct-text-media.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/acp/event-mapper.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/helpers.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/lifecycle-core.config-guard.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 1118�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/target-parsing.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/cli-utils.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/canvas-host/server.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 264�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/outbound/interactive.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/conversation-label.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-group-access-configure.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/acp/runtime/session-meta.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/cli/command-secret-gateway.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-wizard-helpers.test.ts �[2m(�[22m�[2m88 tests�[22m�[2m)�[22m�[32m 58�[2mms�[22m�[39m
�[32m✓�[39m src/acp/server.startup.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 222�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/install.integration.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 351�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m auto-mints token when no source exists without embedding it into service env �[33m 320�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-helpers.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/channel-config.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/config-cli.integration.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 300�[2mms�[22m�[39m
�[32m✓�[39m src/cli/cron-cli.test.ts �[2m(�[22m�[2m42 tests�[22m�[2m)�[22m�[32m 143�[2mms�[22m�[39m
�[32m✓�[39m src/channels/channels-misc.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 20�[2mms�[22m�[39m
�[32m✓�[39m src/cli/deps.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/channels/allowlists/resolve-utils.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/lifecycle.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 34�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/probe.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/status.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/acp/persistent-bindings.lifecycle.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/command-secret-targets.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/acp/translator.stop-reason.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli.coverage.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 64�[2mms�[22m�[39m
�[32m✓�[39m src/acp/session.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/argv.test.ts �[2m(�[22m�[2m74 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/cli/command-secret-resolution.coverage.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/channels/allow-from.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/config-set-input.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/banner.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/command-options.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/draft-stream-controls.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/channels/typing-start-guard.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/lifecycle-core.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/acp/secret-file.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/channel-options.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/devices-cli.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/acp/policy.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 24�[2mms�[22m�[39m
�[32m✓�[39m src/channels/typing.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 27�[2mms�[22m�[39m
�[32m✓�[39m src/channels/native-command-session-targets.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/status.gather.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/register-service-commands.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/acp/runtime/session-identifiers.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/cli/acp-cli.option-collisions.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 27�[2mms�[22m�[39m
�[32m✓�[39m src/bootstrap/node-extra-ca-certs.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/restart-health.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/cli/cron-cli/shared.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/canvas-host/server.state-dir.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli-compat.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/mention-gating.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/command-source.test-helpers.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/cli/completion-cli.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 515�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m defers zsh registration until compinit is available �[33m 509�[2mms�[22m�[39m
�[32m✓�[39m src/channels/account-snapshot-fields.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/status.print.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/container-target.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 38�[2mms�[22m�[39m
�[32m✓�[39m src/acp/runtime/errors.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/install.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cli/completion-fish.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/allowlist-match.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/config-set-mode.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/daemon-cli/shared.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m41 passed�[39m�[22m�[90m (41)�[39m
�[2m Tests �[22m �[1m�[32m452 passed�[39m�[22m�[90m (452)�[39m
�[2m Start at �[22m 03:32:09
�[2m Duration �[22m 26.20s�[2m (transform 10.86s, setup 39.45s, import 8.39s, tests 3.33s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-3 code=0 elapsed=27.5s
[test-parallel] start unit-fast-batch-4 workers=2 filters=all
�[32m✓�[39m src/acp/translator.cancel-scoping.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/acp/client.test.ts �[2m(�[22m�[2m46 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/acp/translator.session-rate-limit.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/acp/translator.prompt-prefix.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/acp/runtime/registry.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/acp/control-plane/runtime-cache.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/inbound-debounce-policy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/acp/translator.set-session-mode.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/acp/session-mapper.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/channels/config-presence.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/ack-reactions.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/location.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/channels/model-overrides.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/bootstrap/node-startup-env.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/channels/command-gating.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/acp/runtime/error-text.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/program-context.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/message/helpers.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.agent.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/action-reparse.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/build-program.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/gateway-cli/run.option-collisions.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[33m 985�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugins-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/preaction.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 299�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/message/register.thread.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugins-cli.update.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/config-guard.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugins-cli.install.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 101�[2mms�[22m�[39m
�[32m✓�[39m src/cli/exec-approvals-cli.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/cli/gateway-cli.coverage.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[33m 333�[2mms�[22m�[39m
�[32m✓�[39m src/cli/nodes-camera.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugins-install-config.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/outbound-send-mapping.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/profile.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/gateway-cli/register.option-collisions.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/build-program.version-alias.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/cli/gateway-cli/run-loop.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/cli/parse-timeout.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugins-cli.uninstall.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/nodes-cli/register.invoke.approval-transport-timeout.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/nodes-cli.coverage.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/mcp-cli.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 70�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugin-registry.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/nodes-media-utils.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/logs-cli.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/cli/pairing-cli.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cli/models-cli.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cli/log-level-option.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/helpers.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/help.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/cli/hooks-cli.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/npm-resolution.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/command-registry.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/plugin-install-plan.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/message-secret-scope.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/command-tree.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/ports.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/context.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m42 passed�[39m�[22m�[90m (42)�[39m
�[2m Tests �[22m �[1m�[32m297 passed�[39m�[22m�[90m (297)�[39m
�[2m Start at �[22m 03:32:36
�[2m Duration �[22m 21.39s�[2m (transform 11.38s, setup 32.71s, import 6.89s, tests 2.06s, environment 5ms)�[22m

[test-parallel] done unit-fast-batch-4 code=0 elapsed=22.4s
[test-parallel] start unit-fast-batch-5 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cli/prompt.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/route.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/routes.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.backup.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program.smoke.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 258�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.maintenance.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/system-cli.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cli/update-cli/restart-helper.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 42�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.status-health-sessions.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cli/update-cli.test.ts �[2m(�[22m�[2m39 tests�[22m�[2m)�[22m�[32m 74�[2mms�[22m�[39m
�[32m✓�[39m src/cli/qr-cli.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.subclis.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.onboard.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/channel-capabilities.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/skills-cli.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cli/tagline.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/cli/skills-cli.formatting.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.message.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/cli/run-main.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.compaction-settings.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 68�[2mms�[22m�[39m
�[32m✓�[39m src/config/config-misc.test.ts �[2m(�[22m�[2m41 tests�[22m�[2m)�[22m�[32m 179�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.allowlist-requires-allowfrom.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 162�[2mms�[22m�[39m
�[32m✓�[39m src/cli/secrets-cli.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.backup-rotation.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 54�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.setup.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/run-main.exit.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cli/security-cli.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/register.configure.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program.force.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/acp/control-plane/manager.test.ts �[2m(�[22m�[2m38 tests�[22m�[2m)�[22m�[33m 57239�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m41 passed�[39m�[22m�[90m (41)�[39m
�[2m Tests �[22m �[1m�[32m311 passed�[39m�[22m�[90m (311)�[39m
�[2m Start at �[22m 03:32:09
�[2m Duration �[22m 66.29s�[2m (transform 15.20s, setup 36.65s, import 2.43s, tests 59.83s, environment 7ms)�[22m

�[32m✓�[39m src/channels/plugins/binding-targets.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 51104�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m delegates ensureReady and ensureSession to the resolved driver �[33m 51098�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-1 code=0 elapsed=67.5s
[test-parallel] start unit-fast-batch-6 workers=2 filters=all
�[32m✓�[39m src/config/config.acp-binding-cutover.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.agent-concurrency-defaults.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/channels/session.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/config/agent-dirs.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/update-cli/shared.command-runner.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-wizard-proxy.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/skills-cli.commands.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/run-main.profile-env.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/config/allowed-values.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/cache-utils.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/message-actions.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cli/update-cli/progress.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/update-cli.option-collisions.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/threading-helpers.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/commands.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/thread-bindings-policy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/bundled-channel-config-runtime.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 534�[2mms�[22m�[39m
�[32m✓�[39m src/cli/progress.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/registry.helpers.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program/root-help.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cli/program.nodes-test-helpers.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m44 passed�[39m�[22m�[90m (44)�[39m
�[2m Tests �[22m �[1m�[32m371 passed�[39m�[22m�[90m (371)�[39m
�[2m Start at �[22m 03:32:58
�[2m Duration �[22m 21.08s�[2m (transform 10.22s, setup 34.70s, import 4.99s, tests 1.58s, environment 5ms)�[22m

[test-parallel] done unit-fast-batch-5 code=0 elapsed=22.1s
[test-parallel] start unit-fast-batch-7 workers=2 filters=all
�[32m✓�[39m src/channels/thread-binding-id.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/targets.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/channels/plugins/group-policy-warnings.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/target-resolvers.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/account-helpers.test.ts �[2m(�[22m�[2m33 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-wizard-binary.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/config-helpers.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/config-schema.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/normalize/targets.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/directory-config-helpers.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/setup-group-access.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/message-actions.security.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/runtime-forwarders.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/sender-label.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.discord-agent-components.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/channels/run-state-machine.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.web-search-provider.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[33m 741�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/directory-adapters.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/pairing-adapters.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/includes.test.ts �[2m(�[22m�[2m48 tests�[22m�[2m)�[22m�[32m 41�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.plugin-validation.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[33m 839�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/registry.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.secrets-schema.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.multi-agent-agentdir-validation.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/bundled.shape-guard.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.env-vars.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 43�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/actions/reaction-message-id.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.write-config.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[33m 479�[2mms�[22m�[39m
�[32m✓�[39m src/config/doc-baseline.integration.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 83�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.nix-integration-u3-u5-u9.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 273�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.identity-defaults.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 133�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.compat.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 77�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/sessions.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[33m 413�[2mms�[22m�[39m
�[32m✓�[39m src/config/dangerous-name-matching.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.observe-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 138�[2mms�[22m�[39m
�[32m✓�[39m src/config/schema.hints.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 46�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.runtime-snapshot-write.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 128�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.talk-validation.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 51�[2mms�[22m�[39m
�[32m✓�[39m src/config/schema.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 197�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.schema-regressions.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.legacy-config-detection.accepts-imessage-dmpolicy.test.ts �[2m(�[22m�[2m32 tests�[22m�[2m)�[22m�[32m 219�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/store.pruning.integration.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[33m 2936�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m saveSessionStore prunes stale entries on write �[33m 862�[2mms�[22m�[39m
�[32m✓�[39m src/config/logging.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.telegram-custom-commands.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.pruning-defaults.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 191�[2mms�[22m�[39m
�[32m✓�[39m src/config/schema.help.quality.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 20�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.telegram-audio-preflight.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/legacy-migrate.test.ts �[2m(�[22m�[2m28 tests�[22m�[2m)�[22m�[32m 129�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.sandbox-docker.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/config/env-preserve-io.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 64�[2mms�[22m�[39m
�[32m✓�[39m src/config/runtime-schema.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 55�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.skills-entries-config.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.runtime-snapshot-load.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 41�[2mms�[22m�[39m
�[32m✓�[39m src/config/schema.base.generated.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 469�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m matches the computed base config schema payload �[33m 466�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/store.session-key-normalization.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 116�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.meta-timestamp-coercion.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.owner-display-secret.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/config/logging-max-file-bytes.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/config/mcp-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 106�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.hooks-module-paths.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.dm-policy-alias.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/plugins-runtime-boundary.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 79�[2mms�[22m�[39m
�[32m✓�[39m src/config/load-channel-config-surface.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 269�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.discord-presence.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.discord.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 88�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/store.pruning.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/cache-fields.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.validation-fails-closed.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 69�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.gateway-tailscale-bind.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.tools-alsoAllow.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/disk-budget.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/config/discord-preview-streaming.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/targets.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 161�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.identity-avatar.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.irc.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/config/redact-snapshot.restore.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/config/redact-snapshot.test.ts �[2m(�[22m�[2m33 tests�[22m�[2m)�[22m�[32m 45�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.talk-api-key-fallback.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/runtime-overrides.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/doc-baseline.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/merge-patch.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/issue-format.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/io.eacces.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/env-preserve.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/delivery-info.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/config/paths.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/config/group-policy.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/env-substitution.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/session-key.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 58�[2mms�[22m�[39m
�[32m✓�[39m src/config/legacy-web-search.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.telegram-topic-agentid.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/config/config.msteams.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m45 passed�[39m�[22m�[90m (45)�[39m
�[2m Tests �[22m �[1m�[32m389 passed�[39m�[22m�[90m (389)�[39m
�[2m Start at �[22m 03:33:16
�[2m Duration �[22m 21.01s�[2m (transform 9.81s, setup 35.20s, import 1.71s, tests 3.90s, environment 3ms)�[22m

�[32m✓�[39m src/config/merge-patch.proto-pollution.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-6 code=0 elapsed=22.1s
[test-parallel] start unit-fast-batch-8 workers=2 filters=all
�[32m✓�[39m src/config/schema.shared.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/normalize-paths.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/config/model-alias-defaults.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/mutate.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/config/sessions/explicit-session-key-normalization.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/config/legacy.shared.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/redact-snapshot.schema.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/runtime-group-policy.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/artifacts.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/store.lock.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/markdown-tables.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions/store-read.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m40 passed�[39m�[22m�[90m (40)�[39m
�[2m Tests �[22m �[1m�[32m300 passed�[39m�[22m�[90m (300)�[39m
�[2m Start at �[22m 03:33:20
�[2m Duration �[22m 19.14s�[2m (transform 7.87s, setup 29.59s, import 2.24s, tests 5.27s, environment 7ms)�[22m

[test-parallel] done unit-fast-batch-7 code=0 elapsed=20.2s
[test-parallel] start unit-fast-batch-9 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/isolated-agent/subagent-followup.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/context-engine/context-engine.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 149�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/delivery-dispatch.double-announce.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 215�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.model-formatting.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.delivery-target-thread-session.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 2078�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses thread session entry when sessionKey is provided and entry exists �[33m 635�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m falls back to main session when sessionKey entry does not exist �[33m 540�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.lane.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 162�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.live-session-model-switch.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 44�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.payload-fallbacks.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.runs-one-shot-main-job-disables-it.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 200�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.message-tool-policy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions.test.ts �[2m(�[22m�[2m37 tests�[22m�[2m)�[22m�[33m 437�[2mms�[22m�[39m
�[32m✓�[39m src/config/slack-token-validation.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.owner-auth.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.signal-groups.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.fast-mode.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/config/talk.normalize.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 52�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions.cache.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 254�[2mms�[22m�[39m
�[32m✓�[39m src/cron/heartbeat-policy.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.talk.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.interim-retry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/delivery-target.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[33m 12540�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m reroutes implicit whatsapp delivery to authorized allowFrom recipient �[33m 12525�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.sandbox-config-preserved.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/thread-bindings-config-keys.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 83�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/helpers.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/session.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/validation.channel-metadata.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 58�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.agent-defaults.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.cron-retention.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.typing-mode.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/config/talk-defaults.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/cron/cron-protocol-conformance.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/config/telegram-webhook-secret.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/config/telegram-webhook-port.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/config/slack-http-config.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cron/delivery.failure-notify.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/config/validation.allowed-values.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cron/delivery.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/telegram-actions-poll.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.session-maintenance-extensions.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 83�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.tts.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.logging-levels.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/config/version.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/delivery-dispatch.named-agent.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent/run.session-key.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/config/sessions.store.imports.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 235�[2mms�[22m�[39m
�[32m✓�[39m src/config/zod-schema.markdown-tables.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/channels/plugins/plugins-channel.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m41 passed�[39m�[22m�[90m (41)�[39m
�[2m Tests �[22m �[1m�[32m354 passed�[39m�[22m�[90m (354)�[39m
�[2m Start at �[22m 03:32:09
�[2m Duration �[22m 212.28s�[2m (transform 13.86s, setup 35.82s, import 202.91s, tests 51.77s, environment 2ms)�[22m

�[32m✓�[39m src/cron/isolated-agent.delivery-awareness.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 156�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-2 code=0 elapsed=213.5s
[test-parallel] start unit-fast-batch-10 workers=2 filters=all
�[32m✓�[39m src/cron/isolated-agent.auth-profile-propagation.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 81�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m43 passed�[39m�[22m�[90m (43)�[39m
�[2m Tests �[22m �[1m�[32m308 passed�[39m�[22m�[90m (308)�[39m
�[2m Start at �[22m 03:33:38
�[2m Duration �[22m 123.72s�[2m (transform 19.69s, setup 33.55s, import 161.59s, tests 14.45s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-8 code=0 elapsed=124.7s
[test-parallel] start unit-fast-batch-11 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/service.prevents-duplicate-timers.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 41�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.rearm-timer-when-running.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.subagent-model.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 942�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m 'uses agents.defaults.subagents.model …' �[33m 426�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.delivers-response-has-heartbeat-ok-but-includes.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 462�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.session-reaper-in-finally.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 236�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.direct-delivery-core-channels.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 510�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.failure-alert.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 51�[2mms�[22m�[39m
�[32m✓�[39m src/cron/store.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[33m 1010�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m skips backup files for runtime-only state churn �[33m 708�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.direct-delivery-forum-topics.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 155�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.main-job-passes-heartbeat-target-last.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/cron/store-migration.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/isolated-agent.helpers.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.persists-delivered-status.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 60�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.every-jobs-fire.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 70�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.store-migration.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 34�[2mms�[22m�[39m
�[32m✓�[39m src/cron/session-reaper.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 88�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/systemd-unavailable.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/bundled/boot-md/handler.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-35195-backup-timing.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-22895-every-next-run.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/docs/slash-commands-doc.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/internal-hooks.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/bundled/session-memory/handler.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[33m 774�[2mms�[22m�[39m
�[32m✓�[39m src/infra/archive.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[33m 634�[2mms�[22m�[39m
�[32m✓�[39m src/entry.version-fast-path.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 375�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.restart-catchup.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 138�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.store.migration.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[33m 794�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m preserves stored custom session targets �[33m 332�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/program-args.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/archive-staging.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 269�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.heartbeat-ok-summary-suppressed.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 60�[2mms�[22m�[39m
�[32m✓�[39m src/docker-build-cache.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.skips-main-jobs-empty-systemevent-text.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 45�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/service-audit.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/runtime-paths.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.read-ops-nonblocking.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 102�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-13992-regression.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/plugin-hooks.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 323�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/schtasks.startup-fallback.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 235�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/loader.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[33m 1279�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/inspect.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m | �[22m�[33m3 skipped�[39m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/cmd-argv.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/image-generation/provider-registry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/docker-image-digests.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 43�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-16156-list-skips-cron.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 66�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/systemd.test.ts �[2m(�[22m�[2m43 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/workspace.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 160�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/schtasks.install.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-17852-daily-skip.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/launchd.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/ops.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 212�[2mms�[22m�[39m
�[32m✓�[39m src/dockerfile.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/bundled/bootstrap-extra-files/handler.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/cron/run-log.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 206�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/hooks-install.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 380�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m installs a hook pack and triggers the handler �[33m 379�[2mms�[22m�[39m
�[32m✓�[39m src/flows/provider-flow.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.list-page-sort-guards.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/docs/clawhub-plugin-docs.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-19676-at-reschedule.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/systemd-hints.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/boundary-path.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 192�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.jobs.test.ts �[2m(�[22m�[2m39 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.get-job.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/systemd-unit.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/entry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/import-url.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/jobs.schedule-error-isolation.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/frontmatter.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/schtasks.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 36�[2mms�[22m�[39m
�[32m✓�[39m src/infra/agent-events.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 36�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.delivery-plan.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 59�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/service-env.test.ts �[2m(�[22m�[2m59 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/schtasks.stop.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 74�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/message-hooks.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.store-load-invalid-main-job.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 54�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/timer.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 43�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/runtime-binary.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/backoff.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/cron/schedule.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.armtimer-tight-loop.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/launchd-restart-handoff.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/boundary-file-read.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.jobs.top-of-hour-stagger.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/cron/normalize.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/infra/bonjour.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/cron/stagger.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/store.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/infra/archive-helpers.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 59�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/gmail-setup-utils.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/state.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service/timeout-policy.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m50 passed�[39m�[22m�[90m (50)�[39m
�[2m Tests �[22m �[1m�[32m333 passed�[39m�[22m�[90m (333)�[39m
�[2m Start at �[22m 03:33:40
�[2m Duration �[22m 141.88s�[2m (transform 19.51s, setup 38.55s, import 235.56s, tests 8.33s, environment 3ms)�[22m

�[32m✓�[39m src/daemon/runtime-hints.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/bonjour-discovery.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-9 code=0 elapsed=142.9s
[test-parallel] start unit-fast-batch-12 workers=2 filters=all
�[32m✓�[39m src/infra/approval-native-delivery.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/service.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/runtime-hints.windows-paths.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/archive-path.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/hooks/fire-and-forget.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/i18n/registry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 40�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/gmail-watcher-lifecycle.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/gmail.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/constants.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/abort-signal.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/flows/search-setup.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 250�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/bundled/boot-md/handler.gateway-startup.integration.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/message-hook-mappers.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/entry.respawn.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/daemon/schtasks-exec.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m39 passed�[39m�[22m�[90m (39)�[39m
�[2m Tests �[22m �[1m�[32m354 passed�[39m�[22m�[2m | �[22m�[33m3 skipped�[39m�[90m (357)�[39m
�[2m Start at �[22m 03:35:42
�[2m Duration �[22m 23.43s�[2m (transform 9.38s, setup 33.93s, import 9.98s, tests 2.07s, environment 2ms)�[22m

�[32m✓�[39m src/infra/canvas-host-url.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-10 code=0 elapsed=24.5s
[test-parallel] start unit-fast-batch-13 workers=2 filters=all
�[32m✓�[39m src/image-generation/live-test-helpers.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/brew.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 33�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/channel-summary.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/channel-activity.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/policy.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/abort-pattern.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/backup-create.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/channel-approval-auth.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/approval-turn-source.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/hooks/module-loader.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/binaries.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/bonjour-errors.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/index.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/build-stamp.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/bonjour-ciao.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-allow-always.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 69�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-channel-runtime.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 73�[2mms�[22m�[39m
�[32m✓�[39m src/infra/detect-package-manager.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 38�[2mms�[22m�[39m
�[32m✓�[39m src/infra/device-pairing.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[33m 1128�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-store.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/infra/clipboard.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/device-bootstrap.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 278�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-parity.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-surface.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/infra/clawhub.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 73�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-safety.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/device-identity.state-dir.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
�[32m✓�[39m src/infra/device-identity.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/fs-safe.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[33m 1101�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-session-target.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/infra/host-env-security.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[33m 2057�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m blocks inherited GIT_SEQUENCE_EDITOR so git rebase -i cannot execute helper payloads �[33m 757�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m blocks inherited GIT_TEMPLATE_DIR so git clone cannot install hook payloads �[33m 494�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m blocks CC overrides so make cannot execute a substituted compiler �[33m 403�[2mms�[22m�[39m
�[32m✓�[39m src/infra/control-ui-assets.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/infra/git-commit.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[33m 444�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-wrapper-resolution.test.ts �[2m(�[22m�[2m64 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/device-auth-store.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/infra/fs-pinned-write-helper.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 299�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-safe-bin-trust.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/env.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-safe-bins.test.ts �[2m(�[22m�[2m50 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/infra-store.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-host.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-analysis.test.ts �[2m(�[22m�[2m47 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/infra/errors.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-flow.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/infra/diagnostic-flags.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-command-resolution.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-obfuscation-detect.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/cli-root-options.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/diagnostic-events.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/infra/dotenv.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 62�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-config.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-safe-bin-policy.test.ts �[2m(�[22m�[2m90 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-safe-bin-runtime-policy.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-inline-eval.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/channels-status-issues.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-forwarder.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-allowlist-matching.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/dedupe.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-allowlist-pattern.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m | �[22m�[33m1 skipped�[39m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-reply.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approvals-policy.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-approval-command-display.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m42 passed�[39m�[22m�[90m (42)�[39m
�[2m Tests �[22m �[1m�[32m666 passed�[39m�[22m�[2m | �[22m�[33m1 skipped�[39m�[90m (667)�[39m
�[2m Start at �[22m 03:36:04
�[2m Duration �[22m 20.50s�[2m (transform 10.67s, setup 33.82s, import 3.95s, tests 2.03s, environment 15ms)�[22m

[test-parallel] done unit-fast-batch-12 code=0 elapsed=21.7s
[test-parallel] start unit-fast-batch-14 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/image-generation/runtime.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 31884�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m generates images through the active image-generation registry �[33m 31863�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m40 passed�[39m�[22m�[90m (40)�[39m
�[2m Tests �[22m �[1m�[32m281 passed�[39m�[22m�[90m (281)�[39m
�[2m Start at �[22m 03:35:43
�[2m Duration �[22m 43.32s�[2m (transform 8.73s, setup 33.90s, import 3.04s, tests 35.45s, environment 2ms)�[22m

[test-parallel] done unit-fast-batch-11 code=0 elapsed=44.1s
[test-parallel] start unit-fast-batch-15 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/network-interfaces.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/ssrf.dispatcher.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-package-dir.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 95�[2mms�[22m�[39m
�[32m✓�[39m src/infra/matrix-migration-snapshot.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 124�[2mms�[22m�[39m
�[32m✓�[39m src/infra/map-size.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/proxy-fetch.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/infra/node-pairing.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 190�[2mms�[22m�[39m
�[32m✓�[39m src/infra/npm-integrity.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/channel-selection.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 34�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/abort.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/jsonl-socket.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 64�[2mms�[22m�[39m
�[32m✓�[39m src/infra/json-files.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 109�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-source-utils.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 48�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-runner.poll.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 3874�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m requires at least two poll options �[33m 2588�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m passes shared poll fields and auto threadId to executePollAction �[33m 399�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m expands maxSelections when pollMulti is enabled �[33m 515�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m defaults maxSelections to one choice when pollMulti is omitted �[33m 370�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/undici-global-dispatcher.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-runner.plugin-dispatch.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 84�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/agent-delivery.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/infra/plugin-approval-forwarder.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/infra/matrix-plugin-helper.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 77�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/delivery-queue.recovery.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 100�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-mode-options.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/json-utf8-bytes.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/infra/openclaw-root.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-runner.media.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[33m 7519�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m hydrates buffer and filename from media for sendAttachment �[33m 2577�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m hydrates buffer and filename from media for bluebubbles upload-file �[33m 478�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m enforces sandboxed attachment paths for attachment actions �[33m 606�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects out-of-sandbox media reference: 'media absolute path' �[33m 438�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects out-of-sandbox media reference: 'mediaUrl absolute path' �[33m 407�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects out-of-sandbox media reference: 'mediaUrl file URL' �[33m 377�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects out-of-sandbox media reference: 'fileUrl file URL' �[33m 343�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects data URLs in media params �[33m 354�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rewrites in-sandbox media references before dry send �[33m 396�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m prefers media over mediaUrl when both aliases are present �[33m 366�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps remote HTTP 'mediaUrl' aliases unchanged under sandbox validation �[33m 376�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps remote HTTP 'fileUrl' aliases unchanged under sandbox validation �[33m 359�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m allows media paths under preferred OpenClaw tmp root �[33m 436�[2mms�[22m�[39m
�[32m✓�[39m src/infra/matrix-migration-config.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 51�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 91�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/fetch-guard.ssrf.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 73�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/thread-id.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/matrix-legacy-state.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 69�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ports-format.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/cfg-threading.guard.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/infra/pairing-files.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/delivery-queue.policy.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/path-env.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 55�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/delivery-queue.storage.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 107�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/outbound-send-service.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-safe-path.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/infra/json-file.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/ssrf.pinning.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/matrix-account-selection.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/machine-name.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
�[32m✓�[39m src/infra/npm-registry-spec.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/current-conversation-bindings.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 63�[2mms�[22m�[39m
�[32m✓�[39m src/infra/network-discovery-display.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/ssrf.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/conversation-id.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/channel-adapters.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/proxy-env.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-target.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/npm-pack-install.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/os-summary.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/best-effort-delivery.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/channel-target.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/net/hostname.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/openclaw-exec-env.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/is-main.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/bound-delivery-router.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/node-shell.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.model-override.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[33m 7611�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m passes heartbeatModelOverride from defaults heartbeat config �[33m 7429�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.ghost-reminder.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 268�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.respects-ackmaxchars-heartbeat-acks.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 192�[2mms�[22m�[39m
�[32m✓�[39m src/infra/gateway-lock.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 110�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.transcript-prune.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.sender-prefers-delivery-target.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 51�[2mms�[22m�[39m
�[32m✓�[39m src/infra/infra-runtime.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 37�[2mms�[22m�[39m
�[32m✓�[39m src/infra/hardlink-guards.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/infra/executable-path.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/infra/home-dir.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/format-time/parse-offsetless-zoned-datetime.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-visibility.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/gaxios-fetch-compat.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/infra/fetch.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/format-time/format-time.test.ts �[2m(�[22m�[2m60 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/infra/exec-wrapper-trust-plan.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-events.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 19�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.scheduler.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-active-hours.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/http-body.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-wake.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/infra/gateway-process-argv.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/git-root.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 109�[2mms�[22m�[39m
�[32m✓�[39m src/infra/host-env-security.policy-parity.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-events-filter.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/gateway-processes.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-reason.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/install-from-npm-spec.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/google-api-base-url.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/file-identity.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/fixed-window-rate-limit.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/gemini-auth.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/heartbeat-runner.returns-default-unset.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 238�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m39 passed�[39m�[22m�[90m (39)�[39m
�[2m Tests �[22m �[1m�[32m424 passed�[39m�[22m�[90m (424)�[39m
�[2m Start at �[22m 03:36:07
�[2m Duration �[22m 120.51s�[2m (transform 22.44s, setup 30.93s, import 150.39s, tests 12.76s, environment 2ms)�[22m

[test-parallel] done unit-fast-batch-13 code=0 elapsed=121.6s
[test-parallel] start unit-fast-batch-16 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/resolve-system-bin.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/infra/retry.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ports.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 52�[2mms�[22m�[39m
�[32m✓�[39m src/infra/restart.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 33�[2mms�[22m�[39m
�[32m✓�[39m src/infra/shell-env.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.auth.plugin.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 354�[2mms�[22m�[39m
�[32m✓�[39m src/infra/run-node.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[33m 369�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.auth.normalizes-keys.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[33m 4598�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m strips embedded CR/LF from env keys �[33m 415�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses config api keys when env and profiles are missing �[33m 306�[2mms�[22m�[39m
�[32m✓�[39m src/infra/restart-stale-pids.test.ts �[2m(�[22m�[2m37 tests�[22m�[2m)�[22m�[32m 20�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[33m 748�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.load.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/session-cost-usage.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 111�[2mms�[22m�[39m
�[32m✓�[39m src/infra/safe-open-sync.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/infra/push-apns.store.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 134�[2mms�[22m�[39m
�[32m✓�[39m src/infra/session-maintenance-warning.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/infra/push-apns.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/push-apns.relay.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.claude.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.minimax.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 41�[2mms�[22m�[39m
�[32m✓�[39m src/infra/scp-host.test.ts �[2m(�[22m�[2m37 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/infra/secret-file.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 40�[2mms�[22m�[39m
�[32m✓�[39m src/infra/runtime-guard.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/infra/restart-sentinel.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 35�[2mms�[22m�[39m
�[32m✓�[39m src/infra/push-apns.auth.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/process-respawn.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.shared.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/infra/secure-random.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/retry-policy.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/deliver.lifecycle.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[33m 6224�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m continues on errors when bestEffort is enabled �[33m 1457�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m calls failDelivery instead of ackDelivery on bestEffort partial failure �[33m 315�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m acks the queue entry when delivery is aborted �[33m 483�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m emits internal message:sent hook with success=true for chunked payload delivery �[33m 529�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m does not emit internal message:sent hook when neither mirror nor sessionKey is provided �[33m 749�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m emits internal message:sent hook when sessionKey is provided without mirror �[33m 714�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m warns when session.agentId is set without a session key �[33m 400�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m mirrors delivered output when mirror options are provided �[33m 358�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m emits message_sent success for text-only deliveries �[33m 418�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m49 passed�[39m�[22m�[90m (49)�[39m
�[2m Tests �[22m �[1m�[32m422 passed�[39m�[22m�[90m (422)�[39m
�[2m Start at �[22m 03:36:25
�[2m Duration �[22m 119.42s�[2m (transform 8.45s, setup 33.56s, import 108.33s, tests 7.70s, environment 21ms)�[22m

[test-parallel] done unit-fast-batch-14 code=0 elapsed=120.4s
[test-parallel] start unit-fast-batch-17 workers=2 filters=all
�[32m✓�[39m src/infra/ssh-tunnel.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.load.plugin.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 105�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.codex.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ssh-config.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 27�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/provider-usage.shared.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/infra/restart.deferral-timeout.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.format.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.zai.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ports-probe.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/provider-usage.fetch.gemini.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/prototype-keys.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ports-lsof.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/shell-inline-command.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/runtime-status.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/skills-remote.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m43 passed�[39m�[22m�[90m (43)�[39m
�[2m Tests �[22m �[1m�[32m419 passed�[39m�[22m�[90m (419)�[39m
�[2m Start at �[22m 03:38:08
�[2m Duration �[22m 22.44s�[2m (transform 6.75s, setup 31.01s, import 4.89s, tests 6.89s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-16 code=0 elapsed=23.2s
[test-parallel] start unit-fast-batch-18 workers=2 filters=all
�[32m✓�[39m src/infra/outbound/message.channels.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 42�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/session-binding-service.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 136�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/outbound/target-errors.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/tool-payload.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/pairing-pending.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/plugin-install-path-warnings.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-runner.context.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/infra/package-json.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/session-context.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/outbound-policy.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/parse-finite-number.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-runner.threading.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/targets.test.ts �[2m(�[22m�[2m55 tests�[22m�[2m)�[22m�[33m 717�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m 'rejects whatsapp without to when allo…' �[33m 473�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/target-normalization.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/target-resolver.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/infra/transport-ready.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 44�[2mms�[22m�[39m
�[32m✓�[39m src/infra/path-safety.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 130�[2mms�[22m�[39m
�[32m✓�[39m src/infra/pairing-token.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 43�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/outbound.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/infra/state-migrations.orphan-keys.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 157�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-params.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 59�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/identity.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/infra/state-migrations.session-roundtrip.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/path-alias-guards.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 213�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/outbound-session.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/update-check.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 43�[2mms�[22m�[39m
�[32m✓�[39m src/infra/package-tag.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/install-sh-version.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 857�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m extracts the semantic version from decorated CLI output �[33m 331�[2mms�[22m�[39m
�[32m✓�[39m src/infra/path-prepend.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/windows-install-roots.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-spec.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tsdown-config.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/sanitize-text.test.ts �[2m(�[22m�[2m27 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media/host.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/format.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/supervisor-markers.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-presence.version.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 439�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/payloads.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/message-action-normalization.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/mcp/plugin-tools-serve.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m src/infra/plain-object.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/path-guards.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/mcp/channel-server.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 63�[2mms�[22m�[39m
�[32m✓�[39m src/infra/voicewake.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/logging/log-file-size-cap.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 174�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/directory-cache.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/outbound/envelope.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m43 passed�[39m�[22m�[90m (43)�[39m
�[2m Tests �[22m �[1m�[32m482 passed�[39m�[22m�[90m (482)�[39m
�[2m Start at �[22m 03:36:27
�[2m Duration �[22m 137.63s�[2m (transform 10.37s, setup 37.38s, import 223.75s, tests 13.16s, environment 3ms)�[22m

�[32m✓�[39m src/infra/unhandled-rejections.fatal-detection.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-15 code=0 elapsed=138.7s
[test-parallel] start unit-fast-batch-19 workers=2 filters=all
�[32m✓�[39m src/logging/logger.browser-import.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 49�[2mms�[22m�[39m
�[32m✓�[39m src/logging/diagnostic.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/logger.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 41�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.table-code.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/infra/update-startup.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 188�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/logging/logger-timestamp.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/logging/console-settings.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-run-command.contract.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/infra/update-runner.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[33m 1907�[2mms�[22m�[39m
�[32m✓�[39m src/media/local-roots.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.blockquote-spacing.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-run-normalize.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/logging/logger-settings.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/media/load-options.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/wsl.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/media/input-files.fetch-guard.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 60�[2mms�[22m�[39m
�[32m✓�[39m src/logging/console-timestamp.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tailscale.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/logging/logger.settings.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/logging/console-capture.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/infra/widearea-dns.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/whatsapp.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/media/fetch.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 69�[2mms�[22m�[39m
�[32m✓�[39m src/infra/state-migrations.fs.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.nested-lists.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.hr-spacing.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-message.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/logging/timestamps.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/media/mime.test.ts �[2m(�[22m�[2m47 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/link-understanding/detect.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/logging/redact.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.table-bullets.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-run-approval-binding.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/media/audio.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/render-aware-chunking.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 48�[2mms�[22m�[39m
�[32m✓�[39m src/infra/update-global.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 95�[2mms�[22m�[39m
�[32m✓�[39m src/media/file-context.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/logging/parse-log-line.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tls/gateway.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/frontmatter.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/logging/subsystem.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/state-migrations.state-dir.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
�[32m✓�[39m src/media/inbound-path-policy.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/logging/logger-env.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/windows-task-restart.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 60�[2mms�[22m�[39m
�[32m✓�[39m src/media/parse.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/media/ffmpeg-exec.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/infra/warning-filter.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media/image-ops.helpers.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/media/base64.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-presence.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 26�[2mms�[22m�[39m
�[32m✓�[39m src/logging/config.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/ir.table-block.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-run-command.test.ts �[2m(�[22m�[2m39 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/markdown/tables.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m41 passed�[39m�[22m�[90m (41)�[39m
�[2m Tests �[22m �[1m�[32m316 passed�[39m�[22m�[90m (316)�[39m
�[2m Start at �[22m 03:38:32
�[2m Duration �[22m 22.39s�[2m (transform 12.74s, setup 38.83s, import 3.79s, tests 716ms, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-18 code=0 elapsed=23.8s
[test-parallel] start unit-fast-batch-20 workers=2 filters=all
�[32m✓�[39m src/interactive/payload.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/unhandled-rejections.test.ts �[2m(�[22m�[2m40 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/system-run-approval-mismatch.contract.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/pairing/setup-code.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 165�[2mms�[22m�[39m
�[32m✓�[39m src/infra/watch-node.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tmp-openclaw-dir.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/approval-delivery-helpers.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tailnet.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-run-approval-context.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/image.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 2245�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m routes minimax-portal image models through the MiniMax VLM endpoint �[33m 1033�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m normalizes deprecated google flash ids before lookup and keeps profile auth selection �[33m 311�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m normalizes gemini 3.1 flash-lite ids before lookup and keeps profile auth selection �[33m 316�[2mms�[22m�[39m
�[32m✓�[39m src/infra/ws.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.proxy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 1015�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m passes fetchFn to audio provider when HTTPS_PROXY is set �[33m 376�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m passes fetchFn to video provider when HTTPS_PROXY is set �[33m 324�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m does not pass fetchFn when no proxy env vars are set �[33m 309�[2mms�[22m�[39m
�[32m✓�[39m src/infra/stable-node-path.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/infra/update-channels.test.ts �[2m(�[22m�[2m32 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/apply.echo-transcript.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[33m 472�[2mms�[22m�[39m
�[32m✓�[39m src/pairing/pairing-store.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[33m 767�[2mms�[22m�[39m
�[32m✓�[39m src/library.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.vision-skip.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 836�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m skips image understanding when the active model supports vision �[33m 413�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses active OpenRouter image models for auto image resolution �[33m 422�[2mms�[22m�[39m
�[32m✓�[39m src/infra/tls/fingerprint.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/apply.test.ts �[2m(�[22m�[2m33 tests�[22m�[2m)�[22m�[33m 516�[2mms�[22m�[39m
�[32m✓�[39m src/media/server.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 161�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/allowlist-config-edit.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.skip-tiny-audio.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 47�[2mms�[22m�[39m
�[32m✓�[39m src/media/store.redirect.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/media/store.test.ts �[2m(�[22m�[2m28 tests�[22m�[2m)�[22m�[32m 104�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/approval-renderers.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media/server.outside-workspace.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/transcribe-audio.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-lifecycle.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundle-claude-inspect.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/provider-entry.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-plugin-metadata.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 31�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/webhook-targets.test.ts �[2m(�[22m�[2m20 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/capability-provider-runtime.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-sources.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-plugin-naming.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundle-mcp.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 143�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/direct-dm.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/persistent-dedupe.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 133�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/group-access.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.video.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 3212�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m auto-selects moonshot for video when google is unavailable �[33m 3198�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-policy.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/keyed-async-queue.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/node-host/invoke-system-run-plan.test.ts �[2m(�[22m�[2m41 tests�[22m�[2m)�[22m�[32m 71�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-dir.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundle-manifest.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/node-host/invoke-system-run.test.ts �[2m(�[22m�[2m39 tests�[22m�[2m)�[22m�[32m 115�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/runtime.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.deepgram.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/runtime-api-guardrails.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 40�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/root-alias.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/media/store.outside-workspace.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/secret-input.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/reply-payload.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/pairing/pairing-messages.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media/web-media.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 53�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/facade-runtime.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 862�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m breaks circular facade re-entry during module evaluation �[33m 830�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/outbound-media.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundle-commands.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 96�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-web-search.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[33m 2089�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps bundled web search fast-path ids aligned with the registry �[33m 1965�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/bundled-provider-auth-env-vars.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/webhook-memory-guards.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-reply-pipeline.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/temp-path.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-pairing.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/plugin-entry-guardrails.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 20�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/index.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/text-chunking.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/webhook-request-guards.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/fetch-auth.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/status-helpers.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/secret-input-schema.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-send-result.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-setup.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/ssrf-policy.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/channel-plugin-ids.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 65�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/captured-registration.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/request-url.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/infra/system-events.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m42 passed�[39m�[22m�[90m (42)�[39m
�[2m Tests �[22m �[1m�[32m414 passed�[39m�[22m�[90m (414)�[39m
�[2m Start at �[22m 03:38:26
�[2m Duration �[22m 55.48s�[2m (transform 23.14s, setup 43.91s, import 40.78s, tests 4.10s, environment 4ms)�[22m

[test-parallel] done unit-fast-batch-17 code=0 elapsed=57.1s
[test-parallel] start unit-fast-batch-21 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/node-host/runner.credentials.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/media-understanding-misc.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/resolve.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-config-helpers.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/providers.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 169�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-wizard.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.auto-audio.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 27370�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses mistral when only mistral key is configured �[33m 27348�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/interactive.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 38�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runner.entries.guards.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hook-runner-global.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/node-host/exec-policy.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-runtime.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 104�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/provider-registry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/installs.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/audio-preflight.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 576�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m runs audio preflight in auto mode when audio config is absent �[33m 329�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/loader.git-path-regression.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 357�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m loads git-style package extension entries when they import plugin-sdk infra-runtime (#49806) �[33m 356�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/attachments.guards.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/copy-bundled-plugin-metadata.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 90�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/loader.test.ts �[2m(�[22m�[2m74 tests�[22m�[2m)�[22m�[33m 4802�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m can scope bundled provider loads to deepseek without hanging �[33m 549�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses the real channel entry in cli-metadata mode for CLI metadata capture �[33m 2627�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.security.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/logger.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/clawhub.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/cli.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/discovery.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 173�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/config-state.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-auth-choices.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-validation.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/conversation-binding.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[33m 945�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/http-registry.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/marketplace.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 117�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime/runtime-discord-typing.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/enable.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.before-agent-start.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.model-override-wiring.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.before-tool-call.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-onboarding-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-discovery.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-catalog.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/runtime.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 13863�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m describes images through the active media-understanding registry �[33m 13846�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/memory-runtime.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 27�[2mms�[22m�[39m
�[32m✓�[39m src/media/read-response-with-limit.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/memory-embedding-providers.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/attachments.normalize.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.before-install.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/pairing/pairing-challenge.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/memory-state.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/format.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/provider-model-helpers.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/media-understanding/defaults.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/hooks.phase-hooks.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/allow-from.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/config-schema.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/approval-auth-helpers.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/lazy-service-module.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/allowlist-resolution.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/pi-package-graph.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/registry.dual-kind-memory-gate.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime/gateway-request-scope.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/min-host-version.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/cli.browser-plugin.integration.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 34�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/command-auth.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m43 passed�[39m�[22m�[90m (43)�[39m
�[2m Tests �[22m �[1m�[32m272 passed�[39m�[22m�[90m (272)�[39m
�[2m Start at �[22m 03:38:55
�[2m Duration �[22m 58.28s�[2m (transform 13.22s, setup 30.74s, import 45.83s, tests 3.68s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-20 code=0 elapsed=59.5s
[test-parallel] start unit-fast-batch-22 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/node-host/invoke.sanitize-env.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m44 passed�[39m�[22m�[90m (44)�[39m
�[2m Tests �[22m �[1m�[32m379 passed�[39m�[22m�[90m (379)�[39m
�[2m Start at �[22m 03:38:46
�[2m Duration �[22m 68.76s�[2m (transform 13.03s, setup 37.37s, import 40.45s, tests 51.75s, environment 6ms)�[22m

[test-parallel] done unit-fast-batch-19 code=0 elapsed=69.9s
[test-parallel] start unit-fast-batch-23 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugins/wired-hooks-subagent.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/target-registry.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/tools.optional.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[33m 1707�[2mms�[22m�[39m
�[32m✓�[39m src/process/windows-command.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/sdk-alias.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 199�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-compaction.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[33m 2411�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m calls runBeforeCompaction in handleAutoCompactionStart �[33m 886�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/audit.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[33m 912�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m short-circuits per-ref fallback for provider-wide batch failures when --allow-exec is enabled �[33m 382�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/status.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 33�[2mms�[22m�[39m
�[32m✓�[39m src/process/supervisor/supervisor.pty-command.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 52�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/resolve.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[33m 1826�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m tolerates stdin write errors when exec provider exits before consuming a large request �[33m 320�[2mms�[22m�[39m
�[32m✓�[39m src/process/exec.windows.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/shared/assistant-identity-values.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime-live-state-guardrails.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/process/exec.no-output-timer.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/process/kill-tree.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 14�[2mms�[22m�[39m
�[32m✓�[39m src/security/temp-path-guard.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 383�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m enforces runtime guardrails for tmpdir joins and weak randomness �[33m 380�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime-plugin-boundary.whatsapp.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m src/routing/resolve-route.test.ts �[2m(�[22m�[2m45 tests�[22m�[2m)�[22m�[32m 62�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/runtime-config-collectors-plugins.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/routing/session-key.test.ts �[2m(�[22m�[2m42 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/exec-secret-ref-id-parity.test.ts �[2m(�[22m�[2m34 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/process/supervisor/supervisor.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/apply.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[33m 1352�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m skips exec SecretRef checks during dry-run unless explicitly allowed �[33m 364�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/runtime-web-tools.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[33m 414�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/ref-contract.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/process/command-queue.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 159�[2mms�[22m�[39m
�[32m✓�[39m src/scripts/ci-changed-scope.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 24�[2mms�[22m�[39m
�[32m✓�[39m src/process/supervisor/adapters/pty.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 33�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/target-registry-pattern.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/stage-bundled-plugin-runtime.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 148�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/web-search-providers.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[33m 3174�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m 'returns bundled providers in alphabet…' �[33m 3144�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/services.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/security/fix.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 631�[2mms�[22m�[39m
�[32m✓�[39m src/process/exec.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m | �[22m�[33m2 skipped�[39m�[2m)�[22m�[33m 410�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/schema-validator.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/security/windows-acl.test.ts �[2m(�[22m�[2m53 tests�[22m�[2m)�[22m�[32m 21�[2mms�[22m�[39m
�[32m✓�[39m src/scripts/canvas-a2ui-copy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/command-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/update.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 12�[2mms�[22m�[39m
�[32m✓�[39m src/process/supervisor/adapters/child.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/runtime.integration.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 2886�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps last-known-good web runtime snapshot when reload introduces unresolved active web refs �[33m 2485�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/uninstall.test.ts �[2m(�[22m�[2m35 tests�[22m�[2m)�[22m�[32m 46�[2mms�[22m�[39m
�[32m✓�[39m src/routing/session-key.continuity.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/sessions/session-lifecycle-events.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/source-display.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime.channel-pin.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/security/skill-scanner.test.ts �[2m(�[22m�[2m35 tests�[22m�[2m)�[22m�[32m 57�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/slots.test.ts �[2m(�[22m�[2m23 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/security/safe-regex.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/web-search-providers.runtime.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 40�[2mms�[22m�[39m
�[32m✓�[39m src/routing/account-lookup.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 58�[2mms�[22m�[39m
�[32m✓�[39m src/security/dm-policy-shared.test.ts �[2m(�[22m�[2m115 tests�[22m�[2m)�[22m�[32m 28�[2mms�[22m�[39m
�[32m✓�[39m src/shared/chat-envelope.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-inbound-claim.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/sessions/send-policy.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-session.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/sessions/session-id.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-message.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/shared/avatar-policy.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/process/supervisor/registry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/configure-plan.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-llm.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/security/external-content.test.ts �[2m(�[22m�[2m65 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/polls.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/configure.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/routing/account-id.test.ts �[2m(�[22m�[2m15 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/provider-env-vars.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/wired-hooks-gateway.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/runtime-gateway-auth-surfaces.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/poll-params.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/sessions/model-overrides.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/scripts/docs-link-audit.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 11�[2mms�[22m�[39m
�[32m✓�[39m src/process/spawn-utils.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/plan.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime/typing-lease.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/sessions/transcript-events.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/secrets/path-utils.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/shared/chat-content.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/plugins/runtime/index.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m42 passed�[39m�[22m�[90m (42)�[39m
�[2m Tests �[22m �[1m�[32m377 passed�[39m�[22m�[90m (377)�[39m
�[2m Start at �[22m 03:39:22
�[2m Duration �[22m 61.35s�[2m (transform 17.69s, setup 33.64s, import 45.95s, tests 7.01s, environment 7ms)�[22m

[test-parallel] done unit-fast-batch-21 code=0 elapsed=62.1s
[test-parallel] start unit-fast-batch-24 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/tasks/task-registry.test.ts �[2m(�[22m�[2m32 tests�[22m�[2m)�[22m�[33m 564�[2mms�[22m�[39m
�[32m✓�[39m src/shared/pid-alive.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/security/audit-extra.sync.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[33m 1465�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m 'small model without sandbox all stays…' �[33m 1462�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m36 passed�[39m�[22m�[90m (36)�[39m
�[2m Tests �[22m �[1m�[32m529 passed�[39m�[22m�[90m (529)�[39m
�[2m Start at �[22m 03:39:55
�[2m Duration �[22m 35.97s�[2m (transform 6.47s, setup 26.32s, import 22.56s, tests 10.09s, environment 2ms)�[22m

[test-parallel] done unit-fast-batch-23 code=0 elapsed=36.7s
[test-parallel] start unit-fast-batch-25 workers=2 filters=all
�[32m✓�[39m src/tasks/flow-registry.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 30�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/flow-registry.store.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 25�[2mms�[22m�[39m
�[32m✓�[39m src/shared/global-singleton.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/shared/net/ipv4.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/shared/tailscale-status.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/shared/device-auth-store.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/usage-aggregates.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/shared/string-sample.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/shared/frontmatter.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/shared/requirements.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-executor-policy.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/shared/process-scoped-map.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/model-param-b.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/config-eval.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/text/reasoning-tags.test.ts �[2m(�[22m�[2m43 tests�[22m�[2m)�[22m�[32m 24�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-executor.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 92�[2mms�[22m�[39m
�[32m✓�[39m src/shared/net/ip.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/tui/osc8-hyperlinks.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m src/tts/provider-registry.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 89�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-stream-assembler.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/tui/theme/theme.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/tui/gateway-chat.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 274�[2mms�[22m�[39m
�[32m✓�[39m src/utils/cjk-chars.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/prompt-select-styled.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/ui-app-settings.agents-files-refresh.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/test-utils/temp-home.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m src/utils/message-channel.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/utils/mask-api-key.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/tui/components/chat-log.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 20�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui.submit-handler.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-overlays.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/test-utils/env.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-session-actions.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/tui/commands.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/table.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m src/utils/delivery-context.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-input-history.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/tui/components/searchable-select-list.test.ts �[2m(�[22m�[2m21 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-event-handlers.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-command-handlers.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/utils/directive-tags.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/tui/components/btw-inline-message.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-formatters.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-local-shell.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/test-utils/session-state-cleanup.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/tui/components/filterable-select-list.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/tui/tui-waiting.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/test-helpers/state-dir-env.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/tts/prepare-text.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/utils/normalize-secret-input.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/test-utils/channel-plugins.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/stream-writer.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/restore.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/tts/status-config.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/safe-text.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m39 passed�[39m�[22m�[90m (39)�[39m
�[2m Tests �[22m �[1m�[32m328 passed�[39m�[22m�[90m (328)�[39m
�[2m Start at �[22m 03:40:32
�[2m Duration �[22m 18.47s�[2m (transform 9.39s, setup 30.52s, import 4.99s, tests 569ms, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-25 code=0 elapsed=19.3s
[test-parallel] start unit-fast-batch-26 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugins/runtime/types.contract.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m45 passed�[39m�[22m�[90m (45)�[39m
�[2m Tests �[22m �[1m�[32m432 passed�[39m�[22m�[2m | �[22m�[33m2 skipped�[39m�[90m (434)�[39m
�[2m Start at �[22m 03:39:54
�[2m Duration �[22m 62.04s�[2m (transform 16.75s, setup 28.92s, import 47.18s, tests 8.80s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-22 code=0 elapsed=62.9s
[test-parallel] start unit-fast-batch-27 workers=2 filters=all

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-gemini.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m)�[22m�[33m 310�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/setup.finalize.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/internal.test.ts �[2m(�[22m�[2m25 tests�[22m�[2m)�[22m�[32m 109�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/backend-config.test.ts �[2m(�[22m�[2m18 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/web-search/runtime.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 409�[2mms�[22m�[39m
�[32m✓�[39m src/utils/usage-format.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-registry.store.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 37�[2mms�[22m�[39m
�[32m✓�[39m src/shared/text/code-regions.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/terminal/ansi.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/shared/text-chunking.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/subagents-format.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/setup.gateway-config.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 104�[2mms�[22m�[39m
�[32m✓�[39m src/shared/net/redact-sensitive-url.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/shared/entry-metadata.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/query-expansion.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 32�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-registry.audit.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m src/shared/node-list-parse.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/string-normalization.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-voyage.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m src/shared/device-auth.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/shared/entry-status.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-voyage.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 91�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/committer.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 1950�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m accepts supported path argument shapes �[33m 1372�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m commits changelog-only changes without pulling in unrelated dirty files �[33m 574�[2mms�[22m�[39m
�[32m✓�[39m src/shared/node-resolve.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 10�[2mms�[22m�[39m
�[32m✓�[39m src/shared/operator-scope-compat.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/shared/text/assistant-visible-text.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/shared/node-match.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m src/shared/gateway-bind-url.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/shared/text/join-segments.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[33m 10090�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses remote baseUrl/apiKey and merges headers �[33m 3069�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m builds Mistral embeddings requests with bearer auth �[33m 336�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps explicit model when openai is selected �[33m 304�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m handles zero vector without division by zero �[33m 535�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m sanitizes non-finite values before normalization �[33m 801�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m normalizes batch embeddings to magnitude ~1.0 �[33m 367�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m loads the model only once when embedBatch is called concurrently �[33m 791�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m retries initialization after a transient ensureContext failure �[33m 701�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m shares initialization when embedQuery and embedBatch start concurrently �[33m 746�[2mms�[22m�[39m
�[32m✓�[39m src/utils/queue-helpers.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/appcast.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-registry-import-boundary.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 1268�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps direct task-registry imports on the approved read-model seam �[33m 1267�[2mms�[22m�[39m
�[32m✓�[39m src/tasks/task-executor-boundary.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 1467�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps raw task lifecycle mutators behind task internals �[33m 1467�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/setup.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 84�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-ollama.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[33m 2883�[2mms�[22m�[39m
�[32m✓�[39m src/shared/chat-message-content.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m40 passed�[39m�[22m�[90m (40)�[39m
�[2m Tests �[22m �[1m�[32m284 passed�[39m�[22m�[90m (284)�[39m
�[2m Start at �[22m 03:40:25
�[2m Duration �[22m 45.93s�[2m (transform 12.39s, setup 25.11s, import 61.74s, tests 3.62s, environment 2ms)�[22m

[test-parallel] done unit-fast-batch-24 code=0 elapsed=46.8s
[test-parallel] start unit-fast-batch-28 workers=2 filters=all
�[32m✓�[39m src/version.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 34�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/qmd-process.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/session-files.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 27�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-gemini.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 16�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embedding-chunk-limits.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-http.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m packages/plugin-package-contract/src/index.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/session.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/utils.test.ts �[2m(�[22m�[2m26 tests�[22m�[2m)�[22m�[32m 23�[2mms�[22m�[39m
�[32m✓�[39m src/utils/utils-misc.test.ts �[2m(�[22m�[2m22 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/qmd-scope.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-output.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-remote-fetch.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/post-json.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-status.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/setup.completion.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/batch-error-utils.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-planner.test.ts �[2m(�[22m�[2m27 tests�[22m�[2m)�[22m�[33m 9447�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m builds a capability-aware plan for mid-memory local runs �[33m 613�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses smaller shared extension batches on constrained local hosts �[33m 532�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m caps CI extension batch concurrency when multiple shared batches are scheduled �[33m 482�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m auto-isolates timed-heavy extension suites in CI �[33m 572�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m scales down mid-tier local concurrency under saturated load �[33m 440�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m splits saturated high-memory local unit bursts into smaller shared batches �[33m 997�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps full local unit runs phased when isolated and heavy lanes are present �[33m 303�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m honors the max-profile top-level no-isolate cap without adding extra lanes �[33m 324�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m splits mixed targeted file selections across surfaces �[33m 364�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m normalizes --bail=0 into collect-all failure policy �[33m 351�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m explains runtime truth using the same catalog and worker policy �[33m 427�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses hotspot-backed memory isolation when explaining unit tests �[33m 408�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m normalizes absolute explain targets before classification �[33m 741�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m explains timed-heavy extension suites as isolated �[33m 468�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m does not leak default-plan shard assignments into targeted units with the same id �[33m 398�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m pins the smallest CI include-file batches to fixed shards �[33m 375�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m removes planner temp artifacts when cleanup runs after planning �[33m 322�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m builds a CI manifest with planner-owned shard counts and matrices �[33m 469�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m suppresses heavy CI jobs in docs-only manifests �[33m 416�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m adds the push-only compat lane to push manifests �[33m 431�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/clack-prompter.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/wizard/setup.secret-input.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m src/utils/transcript-tools.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m src/utils/reaction-level.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-planner.executor-fallback.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 295�[2mms�[22m�[39m
�[32m✓�[39m src/utils/run-with-concurrency.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/qmd-query-parser.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-model-normalize.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m packages/memory-host-sdk/src/host/embeddings-mistral.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m40 passed�[39m�[22m�[90m (40)�[39m
�[2m Tests �[22m �[1m�[32m323 passed�[39m�[22m�[90m (323)�[39m
�[2m Start at �[22m 03:40:51
�[2m Duration �[22m 24.63s�[2m (transform 8.60s, setup 29.92s, import 3.97s, tests 14.35s, environment 2ms)�[22m

�[32m✓�[39m test/scripts/test-extension.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[33m 416�[2mms�[22m�[39m
[test-parallel] done unit-fast-batch-26 code=0 elapsed=25.7s
�[32m✓�[39m test/scripts/ts-topology.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[33m 1246�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m collapses canonical symbols exported by multiple public subpaths �[33m 398�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/slash-command-executor.node.test.ts �[2m(�[22m�[2m33 tests�[22m�[2m)�[22m�[32m 22�[2mms�[22m�[39m
�[32m✓�[39m test/git-hooks-pre-commit.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 630�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m does not treat staged filenames as git-add flags (e.g. --all) �[33m 382�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/controllers/chat.test.ts �[2m(�[22m�[2m28 tests�[22m�[2m)�[22m�[32m 17�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/message-normalizer.test.ts �[2m(�[22m�[2m24 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-config.test.ts �[2m(�[22m�[2m12 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m test/test-env.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 53�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/ios-team-id.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 631�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m resolves a fallback team ID from Xcode team listings (smoke) �[33m 523�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/tool-helpers.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/views/channels.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/slash-commands.node.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-unit-paths.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m test/plugin-extension-import-boundary.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 289�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/views/agents-utils.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/test-runner-manifest.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/check-no-conflict-markers.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 134�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-parallel.test.ts �[2m(�[22m�[2m35 tests�[22m�[2m)�[22m�[33m 12424�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps serial profile on split unit lanes instead of one giant unit worker �[33m 495�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m recycles default local unit-fast runs into bounded batches �[33m 960�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps legacy base-pinned targeted reruns on dedicated forks lanes �[33m 525�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m reports capability-derived output for mid-memory local macOS hosts �[33m 513�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses higher shared extension worker counts on high-memory local hosts �[33m 1114�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m starts isolated channel lanes before shared extension batches on high-memory local hosts �[33m 494�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses coarser unit-fast batching for high-memory local multi-surface runs �[33m 600�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses earlier targeted channel batching on high-memory local hosts �[33m 588�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m uses targeted unit batching on high-memory local hosts �[33m 640�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m explains targeted file ownership and execution policy �[33m 626�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m routes targeted contract tests through the contracts config �[33m 576�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m prints the planner-backed CI manifest as JSON �[33m 457�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m writes CI workflow outputs in ci mode �[33m 475�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m writes install-smoke outputs in install-smoke mode �[33m 446�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m writes bun outputs in ci-bun mode �[33m 416�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m passes through vitest --mode values that are not wrapper runtime overrides �[33m 405�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m prints collect-all failure policy in planner output for wrapper-native flag �[33m 435�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m maps --bail=0 to collect-all failure policy in planner output �[33m 444�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects unknown explicit surface names �[33m 450�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m supports the explicit contracts surface �[33m 535�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m rejects explicit existing files that are not known test files �[33m 612�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/check-no-random-messaging-tmp.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/check-channel-agnostic-boundaries.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/audit-seams.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-update-memory-hotspots-utils.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m test/official-channel-catalog.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-runner-manifest.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/runtime-postbuild.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 74�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/check-no-raw-window-open.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m
�[32m✓�[39m test/release-check.test.ts �[2m(�[22m�[2m19 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m test/openclaw-npm-release-check.test.ts �[2m(�[22m�[2m31 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/postinstall-bundled-plugins.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 42�[2mms�[22m�[39m
�[32m✓�[39m test/extension-test-boundary.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 428�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps plugin-owned behavior suites under the bundled plugin tree �[33m 427�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/check-file-utils.test.ts �[2m(�[22m�[2m4 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/write-cli-startup-metadata.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m
�[32m✓�[39m test/architecture-smells.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 1265�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m produces stable sorted output �[33m 700�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m script json output matches the collector �[33m 565�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/run-vitest-profile.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m test/openclaw-npm-postpublish-verify.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/stage-bundled-plugin-runtime-deps.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 8�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/ui.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m test/plugin-npm-release.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m test/scripts/test-report-utils.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m31 passed�[39m�[22m�[90m (31)�[39m
�[2m Tests �[22m �[1m�[32m248 passed�[39m�[22m�[90m (248)�[39m
�[2m Start at �[22m 03:40:57
�[2m Duration �[22m 29.93s�[2m (transform 7.85s, setup 25.71s, import 3.89s, tests 29.34s, environment 3ms)�[22m

[test-parallel] done unit-fast-batch-27 code=0 elapsed=30.8s
�[32m✓�[39m ui/src/ui/app-chat.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 188�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/views/chat.test.ts �[2m(�[22m�[2m35 tests�[22m�[2m)�[22m�[32m 210�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-unit-config.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 6�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-scoped-config.test.ts �[2m(�[22m�[2m10 tests�[22m�[2m)�[22m�[32m 4�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/controllers/agents.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 7�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/message-extract.test.ts �[2m(�[22m�[2m5 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-extensions-config.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[32m 3�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/views/usage-render-details.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/export.node.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 2�[2mms�[22m�[39m
�[32m✓�[39m test/ui.presenter-next-run.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 5�[2mms�[22m�[39m
�[32m✓�[39m test/vitest-performance-config.test.ts �[2m(�[22m�[2m8 tests�[22m�[2m)�[22m�[32m 1�[2mms�[22m�[39m
�[32m✓�[39m ui/src/ui/chat/tool-cards.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[32m 15�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m23 passed�[39m�[22m�[90m (23)�[39m
�[2m Tests �[22m �[1m�[32m242 passed�[39m�[22m�[90m (242)�[39m
�[2m Start at �[22m 03:41:12
�[2m Duration �[22m 23.13s�[2m (transform 11.21s, setup 38.34s, import 1.76s, tests 570ms, environment 1.89s)�[22m

[test-parallel] done unit-fast-batch-28 code=0 elapsed=24.2s
[test-parallel] start unit-qr-dashboard.integration-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cli/qr-dashboard.integration.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 17673�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Start at �[22m 03:41:35
�[2m Duration �[22m 21.36s�[2m (transform 2.51s, setup 3.52s, import 14ms, tests 17.67s, environment 0ms)�[22m

[test-parallel] done unit-qr-dashboard.integration-isolated code=0 elapsed=22.0s
[test-parallel] start unit-config.legacy-config-detection.rejects-routing-allowfrom-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/config/config.legacy-config-detection.rejects-routing-allowfrom.test.ts �[2m(�[22m�[2m52 tests�[22m�[2m)�[22m�[32m 63�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m52 passed�[39m�[22m�[90m (52)�[39m
�[2m Start at �[22m 03:41:57
�[2m Duration �[22m 3.49s�[2m (transform 1.14s, setup 3.27s, import 11ms, tests 63ms, environment 0ms)�[22m

[test-parallel] done unit-config.legacy-config-detection.rejects-routing-allowfrom-isolated code=0 elapsed=4.1s
[test-parallel] start unit-plugin-auto-enable-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/config/plugin-auto-enable.test.ts �[2m(�[22m�[2m38 tests�[22m�[2m)�[22m�[33m 11240�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps auto-enabled WhatsApp config schema-valid �[33m 11088�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m38 passed�[39m�[22m�[90m (38)�[39m
�[2m Start at �[22m 03:42:02
�[2m Duration �[22m 14.67s�[2m (transform 1.13s, setup 3.28s, import 15ms, tests 11.24s, environment 0ms)�[22m

[test-parallel] done unit-plugin-auto-enable-isolated code=0 elapsed=15.3s
[test-parallel] start unit-matrix-legacy-crypto-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/matrix-legacy-crypto.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 136�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m9 passed�[39m�[22m�[90m (9)�[39m
�[2m Start at �[22m 03:42:17
�[2m Duration �[22m 4.15s�[2m (transform 1.39s, setup 3.80s, import 43ms, tests 136ms, environment 0ms)�[22m

[test-parallel] done unit-matrix-legacy-crypto-isolated code=0 elapsed=4.8s
[test-parallel] start unit-state-migrations-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/state-migrations.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[32m 39�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Start at �[22m 03:42:22
�[2m Duration �[22m 4.07s�[2m (transform 1.33s, setup 3.47s, import 410ms, tests 39ms, environment 0ms)�[22m

[test-parallel] done unit-state-migrations-isolated code=0 elapsed=4.7s
[test-parallel] start unit-commands-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugins/commands.test.ts �[2m(�[22m�[2m14 tests�[22m�[2m)�[22m�[32m 18�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m14 passed�[39m�[22m�[90m (14)�[39m
�[2m Start at �[22m 03:42:26
�[2m Duration �[22m 3.61s�[2m (transform 1.27s, setup 3.43s, import 19ms, tests 18ms, environment 0ms)�[22m

[test-parallel] done unit-commands-isolated code=0 elapsed=4.2s
[test-parallel] start unit-package-contract-guardrails-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugin-sdk/package-contract-guardrails.test.ts �[2m(�[22m�[2m7 tests�[22m�[2m)�[22m�[33m 30786�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps matrix crypto WASM in the packed artifact manifest �[33m 30436�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps extension sources on public sdk or local package seams �[33m 336�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m7 passed�[39m�[22m�[90m (7)�[39m
�[2m Start at �[22m 03:42:31
�[2m Duration �[22m 34.27s�[2m (transform 1.18s, setup 3.33s, import 17ms, tests 30.79s, environment 0ms)�[22m

[test-parallel] done unit-package-contract-guardrails-isolated code=0 elapsed=34.9s
[test-parallel] start unit-runtime.coverage-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/secrets/runtime.coverage.test.ts �[2m(�[22m�[2m2 tests�[22m�[2m)�[22m�[33m 682�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m handles every openclaw.json registry target when configured as active �[33m 488�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Start at �[22m 03:43:05
�[2m Duration �[22m 4.71s�[2m (transform 1.65s, setup 3.84s, import 43ms, tests 682ms, environment 0ms)�[22m

[test-parallel] done unit-runtime.coverage-isolated code=0 elapsed=5.3s
[test-parallel] start unit-runtime-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/secrets/runtime.test.ts �[2m(�[22m�[2m67 tests�[22m�[2m)�[22m�[33m 391�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m67 passed�[39m�[22m�[90m (67)�[39m
�[2m Start at �[22m 03:43:11
�[2m Duration �[22m 4.05s�[2m (transform 1.41s, setup 3.46s, import 49ms, tests 391ms, environment 0ms)�[22m

[test-parallel] done unit-runtime-isolated code=0 elapsed=4.7s
[test-parallel] start unit-audit-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/security/audit.test.ts �[2m(�[22m�[2m73 tests�[22m�[2m)�[22m�[33m 984�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m73 passed�[39m�[22m�[90m (73)�[39m
�[2m Start at �[22m 03:43:15
�[2m Duration �[22m 20.81s�[2m (transform 1.99s, setup 3.49s, import 16.20s, tests 984ms, environment 0ms)�[22m

[test-parallel] done unit-audit-isolated code=0 elapsed=21.4s
[test-parallel] start unit-heavy-1 workers=1 filters=2

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m test/extension-plugin-sdk-boundary.test.ts �[2m(�[22m�[2m3 tests�[22m�[2m)�[22m�[33m 1150�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m stays empty and sorted �[33m 1147�[2mms�[22m�[39m
�[32m✓�[39m src/cron/service.issue-regressions.test.ts �[2m(�[22m�[2m39 tests�[22m�[2m)�[22m�[32m 197�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Tests �[22m �[1m�[32m42 passed�[39m�[22m�[90m (42)�[39m
�[2m Start at �[22m 03:43:37
�[2m Duration �[22m 26.55s�[2m (transform 4.51s, setup 4.01s, import 21.01s, tests 1.35s, environment 0ms)�[22m

[test-parallel] done unit-heavy-1 code=0 elapsed=27.2s
[test-parallel] start unit-heavy-2 workers=1 filters=3

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/hooks/install.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[33m 743�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/channel-import-guardrails.test.ts �[2m(�[22m�[2m11 tests�[22m�[2m)�[22m�[33m 5523�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps bundled extension source files off root and compat plugin-sdk imports �[33m 353�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps core production files off plugin-private src imports �[33m 469�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps extension production files off other extensions' private src imports �[33m 4507�[2mms�[22m�[39m
�[32m✓�[39m src/plugin-sdk/subpaths.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[33m 333�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m keeps runtime entry subpaths importable �[33m 319�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m3 passed�[39m�[22m�[90m (3)�[39m
�[2m Tests �[22m �[1m�[32m30 passed�[39m�[22m�[90m (30)�[39m
�[2m Start at �[22m 03:44:04
�[2m Duration �[22m 11.46s�[2m (transform 2.26s, setup 4.56s, import 138ms, tests 6.60s, environment 0ms)�[22m

[test-parallel] done unit-heavy-2 code=0 elapsed=12.2s
[test-parallel] start unit-heavy-3 workers=1 filters=2

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugin-sdk/index.bundle.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 10381�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m emits importable bundled subpath entries �[33m 10379�[2mms�[22m�[39m
�[32m✓�[39m test/web-search-provider-boundary.test.ts �[2m(�[22m�[2m1 test�[22m�[2m)�[22m�[33m 553�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m stays empty, core-only, and sorted �[33m 552�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Tests �[22m �[1m�[32m2 passed�[39m�[22m�[90m (2)�[39m
�[2m Start at �[22m 03:44:16
�[2m Duration �[22m 14.71s�[2m (transform 1.18s, setup 3.60s, import 34ms, tests 10.93s, environment 0ms)�[22m

[test-parallel] done unit-heavy-3 code=0 elapsed=15.3s
[test-parallel] start unit-channel-resolution-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/outbound/channel-resolution.test.ts �[2m(�[22m�[2m9 tests�[22m�[2m)�[22m�[32m 42�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m9 passed�[39m�[22m�[90m (9)�[39m
�[2m Start at �[22m 03:44:32
�[2m Duration �[22m 3.96s�[2m (transform 1.43s, setup 3.76s, import 14ms, tests 42ms, environment 0ms)�[22m

[test-parallel] done unit-channel-resolution-memory-isolated code=0 elapsed=4.7s
[test-parallel] start unit-run.skill-filter-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/isolated-agent/run.skill-filter.test.ts �[2m(�[22m�[2m13 tests�[22m�[2m)�[22m�[32m 13�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m13 passed�[39m�[22m�[90m (13)�[39m
�[2m Start at �[22m 03:44:36
�[2m Duration �[22m 23.83s�[2m (transform 4.23s, setup 3.63s, import 20.03s, tests 13ms, environment 0ms)�[22m

[test-parallel] done unit-run.skill-filter-memory-isolated code=0 elapsed=24.5s
[test-parallel] start unit-deliver-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/infra/outbound/deliver.test.ts �[2m(�[22m�[2m45 tests�[22m�[2m)�[22m�[33m 820�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m45 passed�[39m�[22m�[90m (45)�[39m
�[2m Start at �[22m 03:45:01
�[2m Duration �[22m 85.30s�[2m (transform 1.59s, setup 3.66s, import 80.66s, tests 820ms, environment 0ms)�[22m

[test-parallel] done unit-deliver-memory-isolated code=0 elapsed=85.9s
[test-parallel] start unit-isolated-agent.uses-last-non-empty-agent-text-as-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/isolated-agent.uses-last-non-empty-agent-text-as.test.ts �[2m(�[22m�[2m16 tests�[22m�[2m)�[22m�[33m 436�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m16 passed�[39m�[22m�[90m (16)�[39m
�[2m Start at �[22m 03:46:27
�[2m Duration �[22m 21.89s�[2m (transform 2.53s, setup 3.54s, import 17.77s, tests 436ms, environment 0ms)�[22m

[test-parallel] done unit-isolated-agent.uses-last-non-empty-agent-text-as-memory-isolated code=0 elapsed=22.5s
[test-parallel] start unit-isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true.test.ts �[2m(�[22m�[2m17 tests�[22m�[2m)�[22m�[33m 466�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m17 passed�[39m�[22m�[90m (17)�[39m
�[2m Start at �[22m 03:46:49
�[2m Duration �[22m 89.54s�[2m (transform 6.14s, setup 9.21s, import 79.60s, tests 466ms, environment 0ms)�[22m

[test-parallel] done unit-isolated-agent.skips-delivery-without-whatsapp-recipient-besteffortdeliver-true-memory-isolated code=0 elapsed=90.3s
[test-parallel] start unit-run.cron-model-override-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/cron/isolated-agent/run.cron-model-override.test.ts �[2m(�[22m�[2m6 tests�[22m�[2m)�[22m�[32m 9�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m6 passed�[39m�[22m�[90m (6)�[39m
�[2m Start at �[22m 03:48:20
�[2m Duration �[22m 24.61s�[2m (transform 3.98s, setup 3.91s, import 20.52s, tests 9ms, environment 0ms)�[22m

[test-parallel] done unit-run.cron-model-override-memory-isolated code=0 elapsed=25.4s
[test-parallel] start unit-manifest-registry-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugins/manifest-registry.test.ts �[2m(�[22m�[2m30 tests�[22m�[2m)�[22m�[32m 151�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m30 passed�[39m�[22m�[90m (30)�[39m
�[2m Start at �[22m 03:48:45
�[2m Duration �[22m 3.87s�[2m (transform 1.20s, setup 3.55s, import 25ms, tests 151ms, environment 0ms)�[22m

[test-parallel] done unit-manifest-registry-memory-isolated code=0 elapsed=4.5s
[test-parallel] start unit-install-memory-isolated workers=1 filters=1

�[1m�[46m RUN �[49m�[22m �[36mv4.1.2 �[39m�[90m/Users/newdldewdl/openclaw-contrib�[39m

�[32m✓�[39m src/plugins/install.test.ts �[2m(�[22m�[2m40 tests�[22m�[2m)�[22m�[33m 1597�[2mms�[22m�[39m
�[33m�[2m✓�[22m�[39m installs scoped archives, rejects duplicate installs, and allows updates �[33m 493�[2mms�[22m�[39m

�[2m Test Files �[22m �[1m�[32m1 passed�[39m�[22m�[90m (1)�[39m
�[2m Tests �[22m �[1m�[32m40 passed�[39m�[22m�[90m (40)�[39m
�[2m Start at �[22m 03:48:49
�[2m Duration �[22m 5.68s�[2m (transform 1.63s, setup 3.86s, import 91ms, tests 1.60s, environment 0ms)�[22m

[test-parallel] done unit-install-memory-isolated code=0 elapsed=6.3s
[test-parallel] summary failurePolicy=fail-fast failedUnits=0 failedTestFiles=0 infraFailures=0 failed twice with retry, classifier , ), so I did not push additional changes in this cycle.

@clawsweeper

clawsweeper Bot commented Apr 26, 2026

Copy link
Copy Markdown
Contributor

Codex automated review: keeping this open.

Keep open. Current main does not implement the low-memory/OOM install handling proposed here, the linked install bug is still open, and the PR discussion raises unresolved maintainer-level tradeoffs around automatic persistent swap creation rather than showing the item is obsolete or safely closable.

Best possible solution:

Continue tracking this item until the missing behavior is implemented or a maintainer decides the product direction.

What I checked:

  • Current main lacks OOM/swap recovery: install_openclaw_npm on current main only retries after build-tool setup and existing npm cleanup paths. There is no low-memory detection, swap provisioning, or OOM-specific retry logic in the shipped installer. (scripts/install.sh:785, 017252e4f8e7)
  • PR behavior is not already shipped: Current main still defaults SHARP_IGNORE_GLOBAL_LIBVIPS=1, and the installer docs describe that same default. This PR is not an implemented_on_main duplicate. (scripts/install.sh:972, 017252e4f8e7)
  • Docs still rely on manual workaround: User-facing install docs still tell low-memory VPS users to add swap manually, which matches the absence of automatic low-memory recovery in the shipped installer. Public docs: docs/install/digitalocean.md. (docs/install/digitalocean.md:62, 017252e4f8e7)
  • Linked bug remains open: Issue [Bug]: npm install failed for openclaw@latest #39447 is still open and reports the one-line installer being OOM-killed on a 1 GB Ubuntu 24.04 DigitalOcean droplet. Follow-up comments describe workarounds such as switching install method or Node version rather than a shipped fix.
  • PR still changes system state in ways that need maintainer judgment: The PR patch still auto-creates /swapfile-openclaw with dd followed by chmod, and PR discussion at head bbde415 includes unresolved security/product concerns about permission timing and automatic persistent swap without opt-in. That is not a conservative cleanup close. (scripts/install.sh:775, bbde4150682c)
  • PR is still active enough to warrant review rather than cleanup close: GitHub check-runs for PR head bbde415 are green, so this is not a stale, unverified PR with no actionable signal. (bbde4150682c)

Remaining risk / open question:

  • Auto-closing would discard a still-open installer bug without an equivalent fix on main.
  • The PR's automatic swap behavior introduces security and product-scope tradeoffs that need explicit maintainer review, not conservative sweeper closure.

Codex Review notes: reviewed against 017252e4f8e7.

@vincentkoc vincentkoc self-assigned this Apr 26, 2026
@steipete

Copy link
Copy Markdown
Contributor

Closing this as obsolete after maintainer verification.

The linked issue #39447 is fixed for the current latest quickstart path:

  • npm install -g openclaw@latest succeeds in node:24-bookworm under --memory=1g --memory-swap=1g.
  • It also succeeds under a tighter --memory=512m --memory-swap=512m cap: added 431 packages in 16s, then OpenClaw 2026.4.24 (cbcfdf6).
  • The actual current scripts/install.sh path also succeeds under the same 512 MB/no-swap cap with onboarding disabled and install verification enabled.

I do not want to land the proposed auto-swap behavior from this PR for a now-unreproduced installer failure. It mutates host swap state during a generic installer run, and the main stated sharp premise is incorrect: sharp's docs say package managers select prebuilt binaries where available, and SHARP_IGNORE_GLOBAL_LIBVIPS=1 skips global libvips detection. It does not force source builds on supported platforms.

Thanks for the focused work here. The right follow-up, if this resurfaces, is a fresh failing log from current latest plus the actual free -h, kernel OOM line, distro, architecture, and npm debug log from that host.

@steipete

Copy link
Copy Markdown
Contributor

Obsolete: current latest installer succeeds under 512 MB/no-swap in live verification; see maintainer comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scripts Repository scripts size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: npm install failed for openclaw@latest

5 participants