Skip to content

fix(onboard): treat refused gateway status as stale - #7143

Closed
HwangJohn wants to merge 6 commits into
NVIDIA:mainfrom
HwangJohn:codex/7087-preserve-shared-gateway
Closed

fix(onboard): treat refused gateway status as stale#7143
HwangJohn wants to merge 6 commits into
NVIDIA:mainfrom
HwangJohn:codex/7087-preserve-shared-gateway

Conversation

@HwangJohn

@HwangJohn HwangJohn commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes stale NemoClaw gateway reuse after the selected OpenShell gateway process is gone but openshell status still reports Gateway: nemoclaw on stderr. Before this change, onboarding could miss that stderr-only refusal and treat the gateway as missing; now it classifies the selected refused gateway as stale and recreates the Docker-driver gateway before sandbox recreation.

Related Issue

Fixes #7087

Changes

  • Capture openshell status stderr during gateway reuse probing so ignored OpenShell probe failures still provide diagnostic state.
  • Teach runner.runCapture to honor explicit includeStderr: true while preserving the existing default stdout-only behavior.
  • Classify Gateway: nemoclaw plus connection-refused/transport-error status output as a stale gateway even when gateway info is unavailable.
  • Add regression coverage for stderr capture, stale gateway state classification, and the onboard reuse snapshot.

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)

Quality Gates

  • Tests added or updated for changed behavior
  • Existing tests cover changed behavior — justification:
  • Tests not applicable — justification:
  • Docs updated for user-facing behavior changes
  • Docs not applicable — justification: no user-facing command, flag, or documentation surface changes; this only fixes internal gateway reuse classification.
  • 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: self-reviewed runner behavior to keep stderr capture opt-in and preserve existing stdout-only defaults.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Verification

  • PR description includes a Signed-off-by: line and every commit appears as Verified in GitHub
  • Normal pre-commit, commit-msg, and pre-push hooks passed, or npm run check:diff passed when hooks were skipped or unavailable
  • Targeted behavior tests pass for the current change set, or tests are marked not applicable above — command/result or justification:
    • DGX Spark Linux: npm run check:diff passed on the pushed fork commit
    • DGX Spark Linux: npm run build:cli passed
    • DGX Spark Linux: npx vitest run --project cli src/lib/runner-argv.test.ts src/lib/onboard/gateway-reuse.test.ts passed, 35 tests
    • DGX Spark Linux: npx vitest run --project integration test/gateway-state.test.ts test/runner-basic.test.ts test/runner.test.ts passed, 119 tests
    • DGX Spark Linux targeted live smoke: after killing the selected default gateway process, the reuse snapshot classified gatewayReuseState: "stale"; onboard --recreate-sandbox restarted the Docker-driver gateway, recreated sandbox codex-7087-a, and did not report Port 8080 is not available
    • Windows local: npx vitest run --project cli src/lib/runner-argv.test.ts -t "stderr" passed, 2 tests
    • Windows local: npx vitest run --project cli src/lib/onboard/gateway-reuse.test.ts passed, 2 tests
    • Windows local: npx vitest run --project integration test/gateway-state.test.ts passed, 55 tests
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result:
  • Quality Gates section completed with required justifications or waivers
  • No secrets, API keys, or credentials committed
  • 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)

Signed-off-by: HwangJohn angelic805@gmail.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved gateway health detection by correctly interpreting broader “server status” and auth-related failure signals as non-connected.
    • Refined gateway reuse state classification: stale now covers unavailable/refused status signals (including stderr-only/ANSI-wrapped cases), and missing covers non-connection status errors.
  • Tests

    • Added/expanded coverage for connection-refused and gateway-info-unavailable scenarios, including mixed stdout/stderr behavior.
    • Added assertions for stderr-inclusive capture behavior and new gateway state/reuse-state regression scenarios (including #7087).

Signed-off-by: HwangJohn <angelic805@gmail.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 18, 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 Jul 18, 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

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c1bee1aa-3628-4d49-aae7-6d7460aa4a34

📥 Commits

Reviewing files that changed from the base of the PR and between 328e228 and 16916f4.

📒 Files selected for processing (1)
  • src/lib/onboard/gateway-reuse.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/onboard/gateway-reuse.test.ts

📝 Walkthrough

Walkthrough

The change adds optional stderr capture to runCapture, passes stderr through gateway status probes, and classifies gateway failures as "stale" or "missing" during gateway reuse and onboarding.

Changes

Gateway reuse failure handling

Layer / File(s) Summary
Capture stderr from failed commands
src/lib/runner.ts, src/lib/runner-argv.test.ts
runCapture optionally combines trimmed stderr with stdout and returns captured output for ignored spawn or non-zero-exit errors, with tests covering both modes.
Classify gateway connection failures
src/lib/state/gateway.ts, test/gateway-state.test.ts
Gateway errors are detected after ANSI stripping; connection errors produce "stale", while non-connection status errors produce "missing".
Pass stderr through gateway status probes
src/lib/onboard/gateway-reuse.ts, src/lib/onboard/gateway-reuse.test.ts, src/lib/onboard/machine/handlers/gateway.test.ts
Gateway status inspection requests stderr, refused status output produces a "stale" reuse snapshot, and onboarding starts the gateway instead of skipping it.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested labels: bug-fix, area: onboarding, area: sandbox

Suggested reviewers: cv

Sequence Diagram(s)

sequenceDiagram
  participant Onboarding
  participant GatewayReuse
  participant runCapture
  participant OpenShell
  Onboarding->>GatewayReuse: inspect gateway state
  GatewayReuse->>runCapture: run status with includeStderr
  runCapture->>OpenShell: execute status probe
  OpenShell-->>runCapture: stdout and stderr
  runCapture-->>GatewayReuse: combined status output
  GatewayReuse-->>Onboarding: stale reuse state
  Onboarding->>OpenShell: start gateway
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change: marking refused gateway status as stale.
Linked Issues check ✅ Passed The PR addresses #7087 by detecting refused/transport-error gateway status and recreating stale gateways during onboarding.
Out of Scope Changes check ✅ Passed All code changes stay within gateway reuse, stderr capture, state classification, and regression tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/lib/state/gateway.ts`:
- Around line 105-117: Update hasGatewayConnectionError to remove generic Error
and client error matches, retaining only connection-specific indicators such as
transport error, Connection refused, Connection reset, and No active gateway.
Ensure isGatewayConnected and getGatewayReuseState no longer classify unrelated
authentication, configuration, or CLI failures as stale, and add a regression
case covering a non-connection error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 8a74aa9e-bd5f-4ce5-b45f-e7014fbb28c4

📥 Commits

Reviewing files that changed from the base of the PR and between 539f407 and 4a74061.

📒 Files selected for processing (6)
  • src/lib/onboard/gateway-reuse.test.ts
  • src/lib/onboard/gateway-reuse.ts
  • src/lib/runner-argv.test.ts
  • src/lib/runner.ts
  • src/lib/state/gateway.ts
  • test/gateway-state.test.ts

Comment thread src/lib/state/gateway.ts Outdated
@github-actions

github-actions Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

Advisor assessment: Informational / high confidence
Next action: Review the warnings below.
Findings: 0 blockers · 1 warning · 0 suggestions
Status: Canonical ledger: 0 blocker(s), 1 warning(s), 0 suggestion(s).

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 fewer warning, the same number of suggestions.

Nemotron output stays in workflow artifacts and does not change the assessment above.

E2E guidance

Advisory only. E2E / PR Gate selects and runs jobs independently.

Recommended E2E: onboard-repair, onboard-resume, cloud-onboard

1 optional E2E recommendation
  • double-onboard
1 warning · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Document the status-error compatibility branch's source boundary and retirement condition

  • Location: src/lib/state/gateway.ts:213
  • Category: docs
  • Problem: The new status-error branch intentionally preserves gateway metadata for auth, configuration, TLS, and CLI failures rather than treating metadata as proof of a stale gateway. Although it has a current onboarding consumer and classifier tests, its comment does not identify the OpenShell behavior/version that creates this mixed status/stderr state, why that upstream source cannot be corrected here, or when this workaround can be removed.
  • Impact: Without provenance and a retirement condition, future changes to OpenShell status output can leave a broad error-text classifier permanently controlling destructive lifecycle behavior, making it difficult to determine whether the workaround remains necessary or safe.
  • Recommendation: Extend the local comment with the originating OpenShell behavior/source boundary, why it must be handled in NemoClaw, and a concrete condition for deleting or revisiting the branch.
  • Verification: Read src/lib/state/gateway.ts around getGatewayReuseState and its status-error tests in test/gateway-state.test.ts; confirm whether they name an upstream source/version and removal condition.
  • Test coverage: Existing classifier tests cover auth/config/TLS/CLI examples; retain them and add a contract fixture tied to the documented upstream status-output version or behavior boundary when that provenance is recorded.
  • Evidence: src/lib/state/gateway.ts:213-220 introduces the metadata-preserving status-error fallback. test/gateway-state.test.ts tests auth, configuration, TLS, and CLI error strings as non-stale. The preceding source-of-truth review found a current consumer and contract coverage but no source provenance or removal condition.

Workflow run details

This automated review informs maintainers. Warnings and suggestions do not require a response. A maintainer decides whether to merge.

Signed-off-by: HwangJohn <angelic805@gmail.com>
Signed-off-by: HwangJohn <angelic805@gmail.com>
@apurvvkumaria apurvvkumaria self-assigned this Jul 18, 2026
apurvvkumaria and others added 3 commits July 18, 2026 13:46
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: HwangJohn <angelic805@gmail.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Co-authored-by: HwangJohn <angelic805@gmail.com>
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>

@apurvvkumaria apurvvkumaria 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 at exact head 16916f4 after independent correctness/security review. The opt-in stderr capture is stripped before argv-only process execution and is scoped to the bounded OpenShell status probe; stale classification is limited to concrete connection failures while auth/config/TLS/CLI errors fail safe without destructive cleanup. Focused coverage includes default/opt-in stderr behavior, false positives, status variants, snapshot propagation, and handler transition. CodeRabbit is resolved, commits are Verified/DCO-compliant, and original-author credit is preserved. Non-blocking follow-up: document the compatibility branch source boundary and retirement condition.

@apurvvkumaria apurvvkumaria 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.

Blocking correctness issue at exact head 16916f443: hasGatewayConnectionError scans the entire cleaned status transcript for Connection refused and the other connection phrases. A healthy status containing informational history such as Previous diagnostic: Connection refused is therefore classified stale and can trigger destructive gateway cleanup.

Please scope all connection-failure phrases to the parsed status-error suffix and add the paired error-vs-informational regression. The credited replacement #7169 already implements that narrower behavior, includes the missing regression, and is green; it should remain the canonical path for #7087.

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Closing as superseded by #7169. The replacement preserves HwangJohn's authorship with a Co-authored-by trailer, covers the same seven-file scope, and adds the missing negative regression so historical 'Connection refused' text is not mistaken for a current gateway failure. #7169 is green and now only awaits independent human review.

apurvvkumaria added a commit that referenced this pull request Jul 25, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Re-publishes the reviewed #7143 change set on a trusted NVIDIA branch so
the required protected E2E jobs can execute. It captures stderr from
failed OpenShell status probes and distinguishes concrete connection
failures from authentication, configuration, TLS, and CLI errors before
deciding that a gateway is stale. This supersedes #7143 solely because
the fork security boundary prevented its required E2E jobs from running.

## Related Issue
Fixes #7087

## Changes
- Keep `runner.runCapture` stdout-only by default while allowing the
bounded gateway status probe to opt into stderr capture.
- Mark the selected gateway stale only for concrete connection failures
and avoid destructive cleanup for unrelated status errors.
- Preserve the reviewed handler transition and add regression coverage
for stderr capture, false positives, status variants, snapshot
propagation, and gateway restart behavior.
- Preserve HwangJohn's original contribution through `Co-authored-by`
trailers, including the current-main sync commit.

## 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)

## Quality Gates
<!-- Check one tests line and one docs line. Check other lines when
applicable. Add every requested justification or approval reference. -->
- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [ ] Docs updated for user-facing behavior changes
- [x] Docs not applicable — justification: no user-facing command, flag,
configuration, output format, or procedure changes; this only fixes
internal gateway reuse classification.
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: exact reviewed change
set approved on
#7143 (review);
the replacement preserves that net diff while syncing current main
mechanically.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review
- [x] Documentation writer subagent reviewed the completed changes
- Result: `no-docs-needed`
- Evidence: The change corrects internal gateway-state classification
and matches the existing documented onboarding behavior. It adds no
command, flag, configuration, output format, or user procedure; no
`docs/` paths need changing. The current-main topper leaves the
effective eight-file product patch byte-identical to the independently
reviewed patch (SHA-256
`6accec058acd136fc90f773c40473b669e4e03de8734e7ee4d571590fc4ee2b0`).
- Agent: Codex Desktop
<!-- docs-review-head-sha: fbe7af2 -->
<!-- docs-review-agents-blob-sha: 9c9b36d -->

## 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 a `Signed-off-by:` line and every
published commit appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and pre-push hooks passed, or
equivalent targeted validation passed when hooks were unavailable
- [x] Targeted behavior tests pass for the current change set — exact
head `280efd274`: `npx vitest run --project cli
src/lib/onboard/gateway-reuse.test.ts
src/lib/onboard/machine/handlers/gateway.test.ts
src/lib/runner-argv.test.ts` (61 tests passed); `npx vitest run
--project integration test/gateway-state.test.ts` (67 tests passed)
- [x] CLI build and type-check pass — `npm run build:cli`; `npm run
typecheck:cli`
- [ ] Applicable broad gate passed — not applicable; the focused runner
and onboarding behavior is covered by the targeted CLI and integration
suites above.
- [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)
- [ ] 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: Apurv Kumaria <akumaria@nvidia.com>

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

* **Bug Fixes**
* Improved gateway reuse detection by capturing and interpreting both
stdout and stderr from OpenShell status (including connection refusals
and authentication-related failures).
* Gateways with connection-related failures are now classified as
**stale** and restarted when appropriate.
* Gateways with non-connection status errors are now classified as
**missing** instead of **stale**.
* Refined gateway “connected”/“disconnected” detection using updated
status-error patterns (OpenShell v0.0.85).
* **Tests**
* Expanded snapshot, scenario, and fixture coverage for stderr-inclusive
output and revised stale/missing classification behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: HwangJohn <angelic805@gmail.com>
Co-authored-by: Aaron Erickson <aerickson@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[All Platforms][Sandbox] Second sandbox onboard loses the shared gateway — gateway process count drops to zero

2 participants