Skip to content

fix(tunnel): detect gateway with rewritten bare 'openclaw' argv (#4951) - #4960

Merged
cv merged 27 commits into
NVIDIA:mainfrom
abhi-0906:fix/issue-4951-tunnel-stop-gateway
Jul 8, 2026
Merged

fix(tunnel): detect gateway with rewritten bare 'openclaw' argv (#4951)#4960
cv merged 27 commits into
NVIDIA:mainfrom
abhi-0906:fix/issue-4951-tunnel-stop-gateway

Conversation

@abhi-0906

@abhi-0906 abhi-0906 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Summary

nemoclaw tunnel stop (and its alias nemoclaw stop) reported success and exited 0 while the in-sandbox OpenClaw gateway — and its channel pollers — kept running. The stop script's process matcher never found the gateway because OpenClaw rewrites its own argv to a bare openclaw after startup. This teaches the matcher that third argv form so the gateway is actually detected and stopped.

Related Issue

Fixes #4951

Root cause

stopSandboxChannels runs an in-sandbox GATEWAY_STOP_SCRIPT (src/lib/tunnel/services.ts) whose find_gateway_pids scans ps -eo args= and matches the gateway by argv. It recognized only:

  • openclaw-gateway (the re-execed binary name), and
  • openclaw gateway run … (the launcher command nemoclaw-start runs).

But OpenClaw sets process.title = 'openclaw' after startup, so the live gateway's argv is just openclaw with no gateway suffix. As a result find_gateway_pids returned empty → the script exit 1reportStopResult interprets exit 1 as "gateway was not running" → the command prints success and exits 0, leaving the gateway and Slack/Telegram/Discord pollers alive. (Same process.title root cause as the sandbox HEALTHCHECK bug, NVB#6282411 / NVB#6282413.)

Changes

  • src/lib/tunnel/services.ts — add a third argv form to the find_gateway_pids awk matcher: a bare openclaw anchored to end-of-string, so it still rejects unrelated names like openclawish. Document the three forms and why example argv tokens must stay out of the awk program body (awk's own argv is captured by the concurrent ps snapshot, so an in-program literal like openclaw gateway makes awk match itself and the kill/verify scan never drains). Export GATEWAY_STOP_SCRIPT for end-to-end testing.
  • src/lib/tunnel/services-sandbox.test.ts — assert the matcher contains all three argv forms, and add two Linux-gated tests that execute the real GATEWAY_STOP_SCRIPT against live processes reproducing each argv form: the bare-argv gateway is found and killed (exit 0), and a non-gateway decoy is spared (exit 1).

Type of Change

  • Code change (feature, bug fix, or refactor)
  • Code change with doc updates
  • Doc only (prose changes, no code sample modifications)
  • Doc only (includes code sample changes)

Verification

  • npx prek run --all-files passes
  • npm test passes
  • Tests added or updated for new or changed behavior
  • No secrets, API keys, or credentials committed
  • Docs updated for user-facing behavior changes
  • npm run docs builds without warnings (doc changes only)
  • Doc pages follow the style guide (doc changes only)
  • New doc pages include SPDX header and frontmatter (new pages only)

Ran locally on the affected files: biome check (clean), tsc -p jsconfig.json (clean), vitest run src/lib/tunnel/services-sandbox.test.ts (17 passed, 2 Linux-gated execution tests skipped on the Windows dev box), plus source-shape and test-size checks. The two Linux-gated execution tests were validated against the compiled script on Ubuntu 24.04 (WSL): bare openclaw killed → exit 0; decoy spared → exit 1.

Summary by CodeRabbit

  • Bug Fixes

    • Improved in-sandbox “tunnel stop” to reliably terminate all relevant gateway process naming variants, including the “bare” gateway form, while sparing unrelated processes.
    • Strengthened the container gateway health-check to safely validate PID reuse by parsing PID/start-time data and verifying the process matches the expected gateway command name.
  • Tests

    • Added Linux-only end-to-end coverage for stop-script matching across multiple gateway argv patterns, including ensuring decoy processes are not terminated.
    • Added a regression test for the health-check fallback when the recorded PID start time is stale.

Signed-off-by: Abhimanyu Kumar abhimanyukumar7290@gmail.com

Signed-off-by: Julie Yaunches jyaunches@nvidia.com

@copy-pr-bot

copy-pr-bot Bot commented Jun 8, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR updates gateway stop matching for the bare openclaw process form and changes PID file writing, reading, and health checks to support an optional recorded start time.

Changes

Gateway stop and PID tracking

Layer / File(s) Summary
Stop script matcher and tests
src/lib/tunnel/services.ts, src/lib/tunnel/services-sandbox.test.ts
The stop script documentation and awk matcher include the bare openclaw process form, and sandbox tests assert the updated matching behavior with unit and Linux-only executed coverage.
PID file write and read
scripts/nemoclaw-start.sh, Dockerfile, test/nemoclaw-start-gateway-health.test.ts, test/sandbox-provisioning.test.ts
record_gateway_pid writes pid or pid starttime, the watchdog and healthcheck read only the first PID field and validate start-time reuse, and health tests accept the extended pidfile format and stale-start detection.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

area: cli, area: sandbox

Suggested reviewers

  • cv
  • jyaunches
  • ericksoa

Poem

🐰 I hop where the gateway names appear,
openclaw plain and clear.
PID files whisper, “read me light,”
one token first, then all is right.
Stop scripts nibble, tests take flight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main fix: tunnel stop now detects gateways whose argv is rewritten to bare 'openclaw'.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@wscurran

wscurran commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this detailed PR about detecting the gateway with rewritten bare 'openclaw' argv. This proposes a way to fix the regression in the tunnel stop functionality.


Related open issues:

1 similar comment
@wscurran

wscurran commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

✨ Thanks for submitting this detailed PR about detecting the gateway with rewritten bare 'openclaw' argv. This proposes a way to fix the regression in the tunnel stop functionality.


Related open issues:

@prekshivyas prekshivyas self-assigned this Jun 22, 2026

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Correct. `process.title = 'openclaw'` after startup made `find_gateway_pids` return empty, so `tunnel stop` silently exited 0. The new awk arm `/(^|[[:space:]/])openclaw[[:space:]]*$/` anchors at EOL, avoiding false matches on `openclaw-gateway` or `openclawish`. The live-process tests with `exec -a 'openclaw' cat` are the right guard for this.

Minor: the 300 ms post-SIGTERM sleep before the liveness check could flake on a heavily loaded CI runner. A short poll loop would be more robust — not a blocker.

@abhi-0906
abhi-0906 force-pushed the fix/issue-4951-tunnel-stop-gateway branch from 97e3f1d to 9f85495 Compare June 22, 2026 18:59
@cv cv added v0.0.67 and removed v0.0.66 labels Jun 23, 2026
@jyaunches jyaunches added v0.0.68 and removed v0.0.67 labels Jun 24, 2026
@abhi-0906
abhi-0906 force-pushed the fix/issue-4951-tunnel-stop-gateway branch from 9f85495 to 6b7015c Compare June 24, 2026 20:01
@jyaunches jyaunches added v0.0.69 and removed v0.0.68 labels Jun 25, 2026
…IA#4951)

`nemoclaw tunnel stop` could not stop the in-sandbox gateway: OpenClaw
rewrites its own argv via process.title after startup, so the running
gateway shows just `openclaw` with no `gateway` suffix. The awk matcher in
GATEWAY_STOP_SCRIPT only recognized `openclaw-gateway` and `openclaw gateway`,
so find_gateway_pids returned empty, reportStopResult misread exit 1 as
"not running", and the command exited 0 while the gateway (and its channel
pollers) kept running.

Add a third argv form to the matcher: a bare `openclaw` anchored to
end-of-string (so it still rejects names like `openclawish`). The example
argv tokens are kept out of the awk program text itself, because awk's argv
is captured by the concurrent `ps` snapshot and any such literal would make
awk match itself and prevent the scan from draining.

Export GATEWAY_STOP_SCRIPT and add Linux-gated tests that execute it against
real processes reproducing each argv form, asserting the bare gateway is
killed (exit 0) and a non-gateway decoy is spared (exit 1).

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
@jyaunches
jyaunches force-pushed the fix/issue-4951-tunnel-stop-gateway branch from 6b7015c to db92038 Compare June 25, 2026 21:18
jyaunches and others added 9 commits June 25, 2026 17:38
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
@github-actions

Copy link
Copy Markdown
Contributor

Vitest E2E Scenario Results — ❌ Some jobs failed

Run: 28238128513
Workflow ref: ci/pr-4960-40fda48c
Requested scenarios: (default — all supported)
Requested jobs: sandbox-survival-vitest
Summary: 0 passed, 1 failed, 0 cancelled, 0 skipped

Job Result
sandbox-survival-vitest ❌ failure

Failed jobs: sandbox-survival-vitest. Check run artifacts for logs.

@github-actions

Copy link
Copy Markdown
Contributor

Selective E2E Results — ✅ All requested jobs passed

Run: 28237439156
Target ref: ci/pr-4960-40fda48c
Requested jobs: cloud-onboard-e2e,tunnel-lifecycle-e2e,sandbox-survival-e2e,issue-2478-crash-loop-recovery-e2e
Summary: 4 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
cloud-onboard-e2e ✅ success
issue-2478-crash-loop-recovery-e2e ✅ success
sandbox-survival-e2e ✅ success
tunnel-lifecycle-e2e ✅ success

@prekshivyas

Copy link
Copy Markdown
Collaborator

@abhi-0906 this is still wanted — the target bug #4951 (nemoclaw tunnel stop reports gateway not running) is still open and nothing has superseded it, and the PR is approved. But the branch is ~235 commits behind main and no longer merges cleanly.

I looked at merging origin/main in: the core fix (src/lib/tunnel/services.ts) merges fine, but there are conflicts in files this PR also changed where main has since evolved the same regions — notably scripts/nemoclaw-start.sh (main reworked record_gateway_pid to capture /proc/<pid>/stat starttime + watchdog-kill records), plus Dockerfile, test/nemoclaw-start-gateway-health.test.ts, and src/lib/tunnel/services-sandbox.test.ts. Reconciling your argv-detection changes with main's new gateway-PID recording is behavior-sensitive, so it's better done by you than guessed at on your behalf.

Could you run git merge origin/main (not rebase — the branch is published) and resolve those, then push? Once it's mergeable I can shepherd it through the merge. Thanks!

Reconcile with main's gateway-PID identity recording (NVIDIA#4952 line): the
branch's interim starttime capture in record_gateway_pid, the Dockerfile
HEALTHCHECK starttime hardening, and the stale-starttime provisioning
test are all superseded by main's caller-supplied start-identity design
and its existing coverage, so those files resolve to main verbatim. The
surviving delta is the tunnel stop argv-detection fix in
src/lib/tunnel/services.ts and its tests.

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
@abhi-0906

Copy link
Copy Markdown
Contributor Author

@prekshivyas Merged origin/main in (73790af). Resolution notes:

  • src/lib/tunnel/services.ts and its tests merged clean; services-sandbox.test.ts now imports from ./services per main's convention.
  • scripts/nemoclaw-start.sh, Dockerfile, test/nemoclaw-start-gateway-health.test.ts, test/sandbox-provisioning.test.ts resolve to main verbatim: this branch's interim starttime capture is superseded by main's caller-supplied start-identity design, and the stale-starttime test duplicates main's "rejects a live PID whose start identity differs from the recorded gateway".
  • Net delta vs main is now 3 files: the argv-detection fix + its tests + a small dcode wrapper test cleanup. Tunnel suite passes locally; the executed GATEWAY_STOP_SCRIPT tests need the Linux runners.

@cv cv added the v0.0.77 label Jul 8, 2026
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28936009201
Workflow ref: ci/pr-4960-prekshivyas
Requested targets: (default — all supported)
Requested jobs: tunnel-lifecycle
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
tunnel-lifecycle ✅ success

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28936440222
Workflow ref: ci/pr-4960-prekshivyas
Requested targets: (default — all supported)
Requested jobs: tunnel-lifecycle
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
tunnel-lifecycle ✅ success

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28936959478
Workflow ref: ci/pr-4960-prekshivyas
Requested targets: (default — all supported)
Requested jobs: tunnel-lifecycle
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
tunnel-lifecycle ✅ success

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28937400229
Workflow ref: ci/pr-4960-prekshivyas
Requested targets: (default — all supported)
Requested jobs: tunnel-lifecycle
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
tunnel-lifecycle ✅ success

Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

E2E Target Results — ✅ All requested jobs passed

Run: 28937887519
Workflow ref: ci/pr-4960-prekshivyas
Requested targets: (default — all supported)
Requested jobs: tunnel-lifecycle
Summary: 1 passed, 0 failed, 0 cancelled, 0 skipped

Job Result
tunnel-lifecycle ✅ success

@prekshivyas prekshivyas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approved exact head ec09600b070ec83fa8ad1c78917d9e82696d2c41 after focused security and runtime review. The trusted gateway identity path now binds validation/read to opened file descriptors, rejects symlinks, unsafe ownership/mode, malformed or surplus PID records, PID reuse, pathname replacement, and stale/dead PID metadata without aborting safe argv scanning. The executed Linux regression suite and all standard CI shards pass. Both PR Advisors recommend merge_as_is: https://github.com/NVIDIA/NemoClaw/actions/runs/28937881639. E2E Advisor requires only tunnel-lifecycle and passed: https://github.com/NVIDIA/NemoClaw/actions/runs/28937883477. Exact-head tunnel-lifecycle passed: https://github.com/NVIDIA/NemoClaw/actions/runs/28937887519. Full CI passed: https://github.com/NVIDIA/NemoClaw/actions/runs/28937845209.

@ericksoa ericksoa added v0.0.78 and removed v0.0.77 labels Jul 8, 2026
@cv
cv merged commit 4576141 into NVIDIA:main Jul 8, 2026
107 checks passed
@cjagwani cjagwani mentioned this pull request Jul 9, 2026
21 tasks
cv pushed a commit that referenced this pull request Jul 9, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user documentation for NemoClaw v0.0.78 by replacing the
unreleased section with release highlights and synchronizing the
affected inference, lifecycle, messaging, and CLI reference pages with
merged behavior.

## Changes

- Publish the v0.0.78 release-notes section with links to the most
specific user guides for each shipped behavior.
- Document authoritative Deep Agents route health, Nemotron Ultra
profile behavior, and Hermes compatible-endpoint context metadata.
- Document forced rebuild recovery after total backup failure and the
ownership-safe tunnel/full-stop behavior.
- Keep command examples and shared agent variants aligned with the
current OpenClaw, Hermes, and Deep Agents interfaces.

Source mapping:

- [#3787](#3787) ->
`docs/about/release-notes.mdx`: Record reliable workspace template
seeding during sandbox startup.
- [#4960](#4960) ->
`docs/about/release-notes.mdx`: Record safer detection of rewritten
OpenClaw gateway processes.
- [#5676](#5676) ->
`docs/about/release-notes.mdx`: Record warning-tolerant agent-list JSON
handling.
- [#5857](#5857) ->
`docs/about/release-notes.mdx`: Record synchronization of explicit
OpenClaw main-agent model state.
- [#5929](#5929) ->
`docs/about/release-notes.mdx`: Record copyable SSH port-forward
guidance for remote dashboards.
- [#6068](#6068) ->
`docs/about/release-notes.mdx`: Record custom-image plugin provenance
reconciliation.
- [#6116](#6116) ->
`docs/about/release-notes.mdx`: Record live-loopback dashboard-forward
recovery.
- [#6122](#6122) ->
`docs/about/release-notes.mdx`: Announce validated, round-trippable
policy YAML output.
- [#6211](#6211) ->
`docs/manage-sandboxes/lifecycle.mdx`, `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Explain the explicit no-backup `rebuild
--force` recovery boundary.
- [#6283](#6283) ->
`docs/about/release-notes.mdx`: Record Hermes WebUI port alignment.
- [#6293](#6293) ->
`docs/inference/switch-inference-providers.mdx`,
`docs/about/release-notes.mdx`: Document compatible-endpoint
context-length probing for Hermes.
- [#6320](#6320) ->
`docs/about/release-notes.mdx`: Record bounded gateway-recovery waits.
- [#6377](#6377) ->
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Explain
rebuild diagnostics and prepared MCP-destroy recovery.
- [#6412](#6412) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document authoritative agent-visible
inference route health.
- [#6421](#6421) ->
`docs/about/release-notes.mdx`: Record the longer quiet-pull window for
managed vLLM images.
- [#6431](#6431) ->
`docs/inference/model-capability-audit.mdx`,
`docs/about/release-notes.mdx`: Document the version-pinned Nemotron
Ultra profile plugin.
- [#6439](#6439) ->
`docs/about/release-notes.mdx`: Summarize the authenticated, pinned
credential-capture helper boundary.
- [#6450](#6450) ->
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document
host-forward cleanup and ownership-safe gateway-port release.
- [#6474](#6474) ->
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/about/release-notes.mdx`: Record composable OpenClaw messaging
runtime loaders.
- [#6475](#6475) ->
`docs/about/release-notes.mdx`: Record removal of the unavailable Kimi
K2.6 production endpoint option.
- [#6480](#6480) ->
`docs/about/release-notes.mdx`: Record stderr routing for the plugin
registration banner.
- [#6481](#6481) ->
`docs/about/release-notes.mdx`: Record post-pull Ollama model discovery
checks.
- [#6482](#6482) ->
`docs/about/release-notes.mdx`: Record Ollama model warm-up after daemon
restart.
- [#6486](#6486) ->
`docs/about/release-notes.mdx`: Publish the opt-in, thread-scoped Deep
Agents auto-approval boundary.
- [#6490](#6490) ->
`docs/about/release-notes.mdx`: Record diagnostics for custom images
missing the managed runtime.
- [#6494](#6494) ->
`docs/inference/model-capability-audit.mdx`,
`docs/about/release-notes.mdx`: Document nonempty tool-call content
preservation and placeholder rejection.
- [#6497](#6497) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document isolated Deep Agents
route-probe output.
- [#6506](#6506) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document observability-preserving
managed route probes.
- [#6508](#6508) ->
`docs/about/release-notes.mdx`: Link the new extension taxonomy and
SDK-readiness reference from the release summary.

Release-source verification: GitHub reports all 29 cited source PRs as
merged with base `main`, and every merge commit is an ancestor of
`origin/main` at `17bf9a6a9688b3b1d69cf4b37d3f23110acb055e`. No
source-mapping mismatches were found.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] Doc only (includes code sample changes)

## Quality Gates

<!-- Check exactly one tests line and one docs line. Check other lines
when applicable. Add every requested justification or approval
reference. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: Documentation-only
release-prep changes; `npm run docs` validates variants, routes, and
Fern content.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: Tests
are not applicable to this documentation-only change set.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) — exited
0 with zero errors; Fern reported the existing unauthenticated
redirect-check and light-mode contrast warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>

---------

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
…IA#4951) (NVIDIA#4960)

## Summary

`nemoclaw tunnel stop` (and its alias `nemoclaw stop`) reported success
and exited `0` while the in-sandbox OpenClaw gateway — and its channel
pollers — kept running. The stop script's process matcher never found
the gateway because OpenClaw rewrites its own argv to a bare `openclaw`
after startup. This teaches the matcher that third argv form so the
gateway is actually detected and stopped.

## Related Issue

Fixes NVIDIA#4951

## Root cause

`stopSandboxChannels` runs an in-sandbox `GATEWAY_STOP_SCRIPT`
(`src/lib/tunnel/services.ts`) whose `find_gateway_pids` scans `ps -eo
args=` and matches the gateway by argv. It recognized only:

- `openclaw-gateway` (the re-execed binary name), and
- `openclaw gateway run …` (the launcher command `nemoclaw-start` runs).

But OpenClaw sets `process.title = 'openclaw'` after startup, so the
live gateway's argv is just `openclaw` with no `gateway` suffix. As a
result `find_gateway_pids` returned empty → the script `exit 1` →
`reportStopResult` interprets exit 1 as *"gateway was not running"* →
the command prints success and exits `0`, leaving the gateway and
Slack/Telegram/Discord pollers alive. (Same `process.title` root cause
as the sandbox HEALTHCHECK bug, NVB#6282411 / NVB#6282413.)

## Changes

- **`src/lib/tunnel/services.ts`** — add a third argv form to the
`find_gateway_pids` awk matcher: a bare `openclaw` anchored to
end-of-string, so it still rejects unrelated names like `openclawish`.
Document the three forms and *why* example argv tokens must stay out of
the awk program body (awk's own argv is captured by the concurrent `ps`
snapshot, so an in-program literal like `openclaw gateway` makes awk
match itself and the kill/verify scan never drains). Export
`GATEWAY_STOP_SCRIPT` for end-to-end testing.
- **`src/lib/tunnel/services-sandbox.test.ts`** — assert the matcher
contains all three argv forms, and add two Linux-gated tests that
**execute** the real `GATEWAY_STOP_SCRIPT` against live processes
reproducing each argv form: the bare-argv gateway is found and killed
(exit 0), and a non-gateway decoy is spared (exit 1).

## Type of Change

- [x] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [ ] Doc only (includes code sample changes)

## Verification

- [ ] `npx prek run --all-files` passes
- [ ] `npm test` passes
- [x] Tests added or updated for new or changed behavior
- [x] No secrets, API keys, or credentials committed
- [ ] Docs updated for user-facing behavior changes
- [ ] `npm run docs` builds without warnings (doc changes only)
- [ ] Doc pages follow the style guide (doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

Ran locally on the affected files: `biome check` (clean), `tsc -p
jsconfig.json` (clean), `vitest run
src/lib/tunnel/services-sandbox.test.ts` (17 passed, 2 Linux-gated
execution tests skipped on the Windows dev box), plus `source-shape` and
`test-size` checks. The two Linux-gated execution tests were validated
against the compiled script on Ubuntu 24.04 (WSL): bare `openclaw`
killed → exit 0; decoy spared → exit 1.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Improved in-sandbox “tunnel stop” to reliably terminate all relevant
gateway process naming variants, including the “bare” gateway form,
while sparing unrelated processes.
* Strengthened the container gateway health-check to safely validate PID
reuse by parsing PID/start-time data and verifying the process matches
the expected gateway command name.

* **Tests**
* Added Linux-only end-to-end coverage for stop-script matching across
multiple gateway argv patterns, including ensuring decoy processes are
not terminated.
* Added a regression test for the health-check fallback when the
recorded PID start time is stale.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>


Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

---------

Signed-off-by: Abhimanyu Kumar <abhimanyukumar7290@gmail.com>
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>
Signed-off-by: Prekshi Vyas <prekshiv@nvidia.com>
Co-authored-by: Julie Yaunches <jyaunches@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Prekshi Vyas <prekshiv@nvidia.com>
Hadar301 pushed a commit to Hadar301/NemoClaw-OpenShift that referenced this pull request Jul 12, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Prepares the user documentation for NemoClaw v0.0.78 by replacing the
unreleased section with release highlights and synchronizing the
affected inference, lifecycle, messaging, and CLI reference pages with
merged behavior.

## Changes

- Publish the v0.0.78 release-notes section with links to the most
specific user guides for each shipped behavior.
- Document authoritative Deep Agents route health, Nemotron Ultra
profile behavior, and Hermes compatible-endpoint context metadata.
- Document forced rebuild recovery after total backup failure and the
ownership-safe tunnel/full-stop behavior.
- Keep command examples and shared agent variants aligned with the
current OpenClaw, Hermes, and Deep Agents interfaces.

Source mapping:

- [NVIDIA#3787](NVIDIA#3787) ->
`docs/about/release-notes.mdx`: Record reliable workspace template
seeding during sandbox startup.
- [NVIDIA#4960](NVIDIA#4960) ->
`docs/about/release-notes.mdx`: Record safer detection of rewritten
OpenClaw gateway processes.
- [NVIDIA#5676](NVIDIA#5676) ->
`docs/about/release-notes.mdx`: Record warning-tolerant agent-list JSON
handling.
- [NVIDIA#5857](NVIDIA#5857) ->
`docs/about/release-notes.mdx`: Record synchronization of explicit
OpenClaw main-agent model state.
- [NVIDIA#5929](NVIDIA#5929) ->
`docs/about/release-notes.mdx`: Record copyable SSH port-forward
guidance for remote dashboards.
- [NVIDIA#6068](NVIDIA#6068) ->
`docs/about/release-notes.mdx`: Record custom-image plugin provenance
reconciliation.
- [NVIDIA#6116](NVIDIA#6116) ->
`docs/about/release-notes.mdx`: Record live-loopback dashboard-forward
recovery.
- [NVIDIA#6122](NVIDIA#6122) ->
`docs/about/release-notes.mdx`: Announce validated, round-trippable
policy YAML output.
- [NVIDIA#6211](NVIDIA#6211) ->
`docs/manage-sandboxes/lifecycle.mdx`, `docs/reference/commands.mdx`,
`docs/about/release-notes.mdx`: Explain the explicit no-backup `rebuild
--force` recovery boundary.
- [NVIDIA#6283](NVIDIA#6283) ->
`docs/about/release-notes.mdx`: Record Hermes WebUI port alignment.
- [NVIDIA#6293](NVIDIA#6293) ->
`docs/inference/switch-inference-providers.mdx`,
`docs/about/release-notes.mdx`: Document compatible-endpoint
context-length probing for Hermes.
- [NVIDIA#6320](NVIDIA#6320) ->
`docs/about/release-notes.mdx`: Record bounded gateway-recovery waits.
- [NVIDIA#6377](NVIDIA#6377) ->
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Explain
rebuild diagnostics and prepared MCP-destroy recovery.
- [NVIDIA#6412](NVIDIA#6412) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document authoritative agent-visible
inference route health.
- [NVIDIA#6421](NVIDIA#6421) ->
`docs/about/release-notes.mdx`: Record the longer quiet-pull window for
managed vLLM images.
- [NVIDIA#6431](NVIDIA#6431) ->
`docs/inference/model-capability-audit.mdx`,
`docs/about/release-notes.mdx`: Document the version-pinned Nemotron
Ultra profile plugin.
- [NVIDIA#6439](NVIDIA#6439) ->
`docs/about/release-notes.mdx`: Summarize the authenticated, pinned
credential-capture helper boundary.
- [NVIDIA#6450](NVIDIA#6450) ->
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/reference/commands.mdx`, `docs/about/release-notes.mdx`: Document
host-forward cleanup and ownership-safe gateway-port release.
- [NVIDIA#6474](NVIDIA#6474) ->
`docs/manage-sandboxes/messaging-channels.mdx`,
`docs/about/release-notes.mdx`: Record composable OpenClaw messaging
runtime loaders.
- [NVIDIA#6475](NVIDIA#6475) ->
`docs/about/release-notes.mdx`: Record removal of the unavailable Kimi
K2.6 production endpoint option.
- [NVIDIA#6480](NVIDIA#6480) ->
`docs/about/release-notes.mdx`: Record stderr routing for the plugin
registration banner.
- [NVIDIA#6481](NVIDIA#6481) ->
`docs/about/release-notes.mdx`: Record post-pull Ollama model discovery
checks.
- [NVIDIA#6482](NVIDIA#6482) ->
`docs/about/release-notes.mdx`: Record Ollama model warm-up after daemon
restart.
- [NVIDIA#6486](NVIDIA#6486) ->
`docs/about/release-notes.mdx`: Publish the opt-in, thread-scoped Deep
Agents auto-approval boundary.
- [NVIDIA#6490](NVIDIA#6490) ->
`docs/about/release-notes.mdx`: Record diagnostics for custom images
missing the managed runtime.
- [NVIDIA#6494](NVIDIA#6494) ->
`docs/inference/model-capability-audit.mdx`,
`docs/about/release-notes.mdx`: Document nonempty tool-call content
preservation and placeholder rejection.
- [NVIDIA#6497](NVIDIA#6497) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document isolated Deep Agents
route-probe output.
- [NVIDIA#6506](NVIDIA#6506) ->
`docs/get-started/quickstart-langchain-deepagents-code.mdx`,
`docs/about/release-notes.mdx`: Document observability-preserving
managed route probes.
- [NVIDIA#6508](NVIDIA#6508) ->
`docs/about/release-notes.mdx`: Link the new extension taxonomy and
SDK-readiness reference from the release summary.

Release-source verification: GitHub reports all 29 cited source PRs as
merged with base `main`, and every merge commit is an ancestor of
`origin/main` at `17bf9a6a9688b3b1d69cf4b37d3f23110acb055e`. No
source-mapping mismatches were found.

## Type of Change

- [ ] Code change (feature, bug fix, or refactor)
- [ ] Code change with doc updates
- [ ] Doc only (prose changes, no code sample modifications)
- [x] Doc only (includes code sample changes)

## Quality Gates

<!-- Check exactly one tests line and one docs line. Check other lines
when applicable. Add every requested justification or approval
reference. -->
- [ ] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: Documentation-only
release-prep changes; `npm run docs` validates variants, routes, and
Fern content.
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [ ] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [ ] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification:
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Verification

<!-- Check each applicable item only when supported by the requested
evidence. Run targeted tests once per relevant change set and rerun
after later edits or hook autofixes that can affect the tested behavior.
Do not rerun hook-covered checks. -->
- [x] PR description includes the DCO sign-off declaration and every
commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run check:diff` passed when hooks were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — command/result or justification: Tests
are not applicable to this documentation-only change set.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result:
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, or credentials committed
- [ ] `npm run docs` builds without warnings (doc changes only) — exited
0 with zero errors; Fern reported the existing unauthenticated
redirect-check and light-mode contrast warnings.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only)
- [ ] New doc pages include SPDX header and frontmatter (new pages only)

---
<!-- DCO sign-off is required in this PR description, and every commit
must appear as Verified in GitHub. Run: git config user.name && git
config user.email -->
Signed-off-by: Charan Jagwani <cjagwani@nvidia.com>

---------

Signed-off-by: cjagwani <cjagwani@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior NV QA Bugs found by the NVIDIA QA Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platforms][CLI&UX] nemoclaw tunnel stop reports gateway not running and exits 0 while in-sandbox openclaw gateway keeps running

6 participants