Skip to content

fix(sandbox): align recreate readiness-wait budget with connect (120s) - #7784

Merged
jyaunches merged 1 commit into
mainfrom
fix/7227-recreate-readiness-wait-budget
Jul 29, 2026
Merged

fix(sandbox): align recreate readiness-wait budget with connect (120s)#7784
jyaunches merged 1 commit into
mainfrom
fix/7227-recreate-readiness-wait-budget

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Problem (#7227)

start's post-recreate recovery waits for OpenShell to re-register a just-recreated sandbox as Ready, then gives up after 30s and surfaces the manual-recover hint. connect's readiness wait (waitForSandboxReadyOrExit) proves the same post-recreate sandbox readiness but allows 120s (NEMOCLAW_CONNECT_TIMEOUT).

On a cold start the sandbox can sit in a transient phase: Error settling window that exceeds 30s but is comfortably within 120s. When it does, the recovery path abandons the sandbox and prints the manual-recover hint, while connect --probe-only — with the larger budget — recovers the exact same sandbox and starts the primary dashboard/API forward. That 4x budget asymmetry is the intermittent start/recovery failure in #7227.

Change

  • Introduce a single GATEWAY_RECOVERY_WAIT_DEFAULT_SECONDS = 120 and use it for both readiness-wait default sites (waitForRecreatedSandboxOpenShellReadyResult and waitForRecoveredSandboxGateway), aligning them with connect.
  • NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS (existing env override) is unchanged.
  • Deliberately untouched because they are different concepts: the agent health-probe timeout (30s) and the post-ready settle pause (NEMOCLAW_GATEWAY_RECOVERY_SETTLE_SECONDS, 25s).

Verification / honesty note

This is a low-probability cold-start race. On latest main it reproduced 1 in 12 start cycles on a DGX Spark and could not be re-triggered deterministically afterward (0 in a further 20 warm + cold retries). Because the timing is non-deterministic, this PR is a principled budget alignment (match the two paths that prove the same readiness) rather than an empirically-timed value — I could not produce a green/red toggle that flips solely on the 30→120 change.

Given that, keeping #7227 open to confirm over repeated cold starts is reasonable; hence Refs rather than Fixes.

Tests

  • New unit test locks the default: with no timeoutSeconds option and no env override, a persistent transient phase: Error is retried past the old 11-attempt (30s) cap — the 12th probe must still be reached. Would fail under the old 30s default.
  • Existing process-recovery suite unchanged and green (42 tests). typecheck:cli and prek clean.

Refs #7227

Signed-off-by: Yanyun Liao yanyunl@nvidia.com

Summary by CodeRabbit

  • Bug Fixes
    • Improved gateway recovery reliability by extending the default readiness window from 30 to 120 seconds.
    • Recovery checks now continue through longer periods of temporary OpenShell errors before reporting failure.

The post-recreate OpenShell readiness wait gave up after 30s, 4x sooner
than `connect`'s `waitForSandboxReadyOrExit` (120s) — even though both
prove the same thing: that a just-recreated sandbox has re-registered as
Ready. On a cold start the sandbox can sit in a transient `phase: Error`
settling window longer than 30s but well within 120s. When that happened,
`start`'s recovery abandoned the sandbox and surfaced the manual-recover
hint, while `connect --probe-only` (with the larger budget) recovered the
exact same sandbox and started the primary dashboard/API forward. That
asymmetry is the intermittent start/recovery failure reported in #7227.

Introduce a single `GATEWAY_RECOVERY_WAIT_DEFAULT_SECONDS = 120` constant
and use it for both readiness-wait default sites
(`waitForRecreatedSandboxOpenShellReadyResult` and
`waitForRecoveredSandboxGateway`). The `NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS`
env override is unchanged. The agent health-probe timeout (30s) and the
post-ready settle pause (25s) are distinct concepts and are left untouched.

This is a low-probability cold-start race that does not reproduce
deterministically, so this is a principled budget alignment rather than an
empirically-timed value; keeping #7227 open to confirm over repeated
cold starts is reasonable.

Refs #7227

Signed-off-by: Yanyun Liao <yanyunl@nvidia.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Recovery readiness now uses a shared 120-second default instead of 30 seconds for recreated-sandbox OpenShell checks and recovered gateway waits. A test verifies readiness succeeds after eleven transient failures and a successful twelfth probe.

Changes

Gateway recovery budget

Layer / File(s) Summary
Shared recovery timeout default
src/lib/actions/sandbox/process-recovery.ts
Introduces a 120-second recovery default and applies it to recreated-sandbox readiness and recovered gateway timeout calculations while retaining environment overrides.
Extended transient retry coverage
src/lib/actions/sandbox/process-recovery.test.ts
Adds coverage for eleven transient OpenShell failures followed by a successful twelfth probe using the default recovery budget.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • NVIDIA/NemoClaw#7650: Updates related recreated-sandbox OpenShell transient-error retry behavior and test coverage.

Suggested labels: area: sandbox, bug-fix

Suggested reviewers: cv, sandl99

🚥 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 It clearly summarizes the main change: increasing sandbox recreate readiness-wait defaults to match connect's 120s budget.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/7227-recreate-readiness-wait-budget

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

@github-code-quality

github-code-quality Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 7d06310 in the fix/7227-recreate-re... branch remains at 96%, unchanged from commit 125ca30 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 7d06310 in the fix/7227-recreate-re... branch remains at 81%, unchanged from commit cf34b72 in the main branch.

Show a code coverage summary of the most impacted files.
File main cf34b72 fix/7227-recreate-re... 7d06310 +/-
src/lib/onboard...box-prebuild.ts 92% 74% -18%
src/lib/actions...ocker-health.ts 82% 65% -17%
src/lib/actions...confirmation.ts 79% 69% -10%
src/lib/onboard...box-gpu-mode.ts 97% 92% -5%
src/lib/actions...light-guards.ts 90% 86% -4%
src/lib/onboard/preflight.ts 80% 80% 0%
src/lib/onboard...host-anchors.ts 90% 94% +4%
src/lib/policy/...ne-exclusion.ts 91% 97% +6%
src/lib/domain/.../connect-env.ts 89% 97% +8%
src/lib/onboard/docker-cdi.ts 70% 80% +10%

Updated July 29, 2026 05:22 UTC

@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

🧹 Nitpick comments (1)
src/lib/actions/sandbox/process-recovery.test.ts (1)

112-147: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the separately changed recovered-gateway default.

This regression test only exercises waitForRecreatedSandboxOpenShellReady. Add a behavioral test where waitForRecoveredSandboxGateway also survives the old 30-second/11-attempt budget; its existing immediate-success test would pass with either default.

🤖 Prompt for 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.

In `@src/lib/actions/sandbox/process-recovery.test.ts` around lines 112 - 147,
Extend the recovery tests with a behavioral case for
waitForRecoveredSandboxGateway that omits timeoutSeconds and the environment
override, returns transient failures for at least 11 probes, then succeeds, and
verifies the 12th probe is reached and recovery succeeds. Keep the existing
immediate-success test unchanged and mirror the default-budget setup used by
waitForRecreatedSandboxOpenShellReady.

Source: Path instructions

🤖 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/actions/sandbox/process-recovery.test.ts`:
- Line 118: Update the test setup around the
NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS environment variable to save its prior
value, then restore that exact value in a finally block after the test
completes, including when assertions or setup fail. Preserve the existing test
behavior while preventing process.env state from leaking into later tests.

---

Nitpick comments:
In `@src/lib/actions/sandbox/process-recovery.test.ts`:
- Around line 112-147: Extend the recovery tests with a behavioral case for
waitForRecoveredSandboxGateway that omits timeoutSeconds and the environment
override, returns transient failures for at least 11 probes, then succeeds, and
verifies the 12th probe is reached and recovery succeeds. Keep the existing
immediate-success test unchanged and mirror the default-budget setup used by
waitForRecreatedSandboxOpenShellReady.
🪄 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: 472a454e-2d75-4af5-bd40-3b88b9b6d210

📥 Commits

Reviewing files that changed from the base of the PR and between eeab81c and 7d06310.

📒 Files selected for processing (2)
  • src/lib/actions/sandbox/process-recovery.test.ts
  • src/lib/actions/sandbox/process-recovery.ts

// retrying a cold-start phase:Error settling window that exceeds the old
// 30s / 11-attempt budget. The 12th probe (past the old 11-attempt cap) must
// still be reached, so the primary dashboard/API forward is not abandoned.
delete process.env.NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS;

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Restore the previous environment value.

This test mutates process.env directly and never restores the prior value, so later tests can become order-dependent. Save the value and restore it in a finally block.

Proposed fix
+    const previousRecoveryWait = process.env.NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS;
     delete process.env.NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS;
+    try {
       // existing assertions
+    } finally {
+      if (previousRecoveryWait === undefined) {
+        delete process.env.NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS;
+      } else {
+        process.env.NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS = previousRecoveryWait;
+      }
+    }
🤖 Prompt for 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.

In `@src/lib/actions/sandbox/process-recovery.test.ts` at line 118, Update the
test setup around the NEMOCLAW_GATEWAY_RECOVERY_WAIT_SECONDS environment
variable to save its prior value, then restore that exact value in a finally
block after the test completes, including when assertions or setup fail.
Preserve the existing test behavior while preventing process.env state from
leaking into later tests.

Source: Path instructions

@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — No blocking findings reported

Advisor assessment: No blocking advisor findings reported
Next action: No advisor follow-up needed.
Findings: 0 blockers · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 0 blockers · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Completed · high confidence · 0 blockers · 1 warning · 0 suggestions
  • Model comparison: normalized findings differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 more 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

1 optional E2E recommendation
  • sandbox-operations

Workflow run details

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

@jyaunches

Copy link
Copy Markdown
Contributor

@yanyunl1991 if you continue working on this, consider a wider refactoring for timeout handling

@jyaunches
jyaunches merged commit 5aacf53 into main Jul 29, 2026
77 of 78 checks passed
@jyaunches
jyaunches deleted the fix/7227-recreate-readiness-wait-budget branch July 29, 2026 13:23
@sandl99 sandl99 mentioned this pull request Jul 30, 2026
23 tasks
cv pushed a commit that referenced this pull request Jul 30, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Add the canonical pre-tag release entry for NemoClaw v0.0.98.
The dated entry records the user-visible changes merged after v0.0.97
and links each release theme to its published documentation.

## Changes

- Add `docs/changelog/2026-07-29.mdx` with the exact `## v0.0.98`
release heading.
- Summarize Hermes 0.19, Deep Agents Code automation and skill safety,
readiness diagnostics, lifecycle recovery, uninstall behavior, messaging
conflicts, dependency hardening, and bounded diagnostics.
- Use the parser-safe MDX SPDX comment and root-absolute routes for
published OpenClaw, Hermes, and Deep Agents documentation.

### Source summary

- [#7849](#7849) ->
`docs/changelog/2026-07-29.mdx`: Record the Hermes 0.19 runtime
migration repairs for cron state, dashboard seeding, and MCP naming.
- [#7662](#7662) ->
`docs/changelog/2026-07-29.mdx`: Record bounded gateway and Docker
subprocess diagnostics.
- [#7850](#7850) ->
`docs/changelog/2026-07-29.mdx`: Record verified no-clobber Deep Agents
Code skill installation.
- [#7848](#7848) ->
`docs/changelog/2026-07-29.mdx`: Record post-reboot delivery-chain
recovery for visible OpenClaw sandboxes.
- [#7831](#7831) ->
`docs/changelog/2026-07-29.mdx`: Record OpenShell gateway-state
preservation during uninstall.
- [#7827](#7827) ->
`docs/changelog/2026-07-29.mdx`: Record the removal of upstream test
sources from published Hermes images.
- [#7775](#7775) ->
`docs/changelog/2026-07-29.mdx`: Record the blocking diagnostic for
unsupported `DOCKER_HOST` values.
- [#7833](#7833) ->
`docs/changelog/2026-07-29.mdx`: Record reviewed Python dependency
baselines for Hermes and Deep Agents Code images.
- [#7771](#7771) ->
`docs/changelog/2026-07-29.mdx`: Record the managed Hermes Agent 0.19.0
upgrade.
- [#7811](#7811) ->
`docs/changelog/2026-07-29.mdx`: Record fail-closed messaging channel
conflict handling.
- [#7797](#7797) ->
`docs/changelog/2026-07-29.mdx`: Record the managed non-interactive Deep
Agents Code JSON envelope.
- [#7782](#7782) ->
`docs/changelog/2026-07-29.mdx`: Record the storage-remediation
readiness capability.
- [#7784](#7784) ->
`docs/changelog/2026-07-29.mdx`: Record the 120-second OpenShell
readiness budget for sandbox recreation.
- [#7810](#7810) ->
`docs/changelog/2026-07-29.mdx`: Record rejection of stale Deep Agents
Code security inventories.

## Type of Change

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

## Quality Gates

- [ ] Tests added or updated for changed behavior
- [x] Existing tests cover changed behavior — justification:
`test/changelog-docs.test.ts` validates the native changelog contract,
including the version heading, MDX SPDX comment, and published routes.
- [ ] Tests not applicable — justification:
- [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:

## Documentation Writer Review

- [x] Documentation writer subagent reviewed the completed changes
- Result: `docs-updated`
- Evidence: `docs/changelog/2026-07-29.mdx` was reviewed against
`docs/CONTRIBUTING.md` and `WRITING.md` for release meaning,
terminology, structure, voice, sentence form, MDX structure, published
routes, and code-sample presentation. The changelog contract passed 6
tests. The docs build completed with 0 errors and 2 existing Fern
warnings.
- Agent: Codex CLI
<!-- docs-review-head-sha: e3221d1 -->
<!-- docs-review-agents-blob-sha: c052d60 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit: Not applicable. `scripts/prepare-dgx-station-host.sh`
is unchanged.
- Station profile/scenario: Not applicable.
- Result: Not applicable.
- Supporting evidence: Not applicable.

## Verification

- [x] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub
- [x] Normal `pre-commit`, `commit-msg`, and `pre-push` hooks passed, or
`npm run validate:pr` passed after refreshing `origin/main` when hooks
were skipped or unavailable
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — `npx vitest run
test/changelog-docs.test.ts` passed 6 tests.
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: Not run for this
documentation-only change.
- [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) — The
build completed with 0 errors and 2 existing Fern 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)
— Native changelog entries use the required parser-safe MDX SPDX comment
and do not use frontmatter.

---
Signed-off-by: San Dang <sdang@nvidia.com>


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

## Summary by CodeRabbit

- **New Features**
- Added managed Hermes upgrades with verified releases, version
reporting, and preserved configuration contracts.
- Improved Deep Agents Code JSON output and skill installation behavior.
  - Added clearer Docker host and system readiness reporting.
  - Improved post-reboot delivery recovery and sandbox readiness timing.
- **Bug Fixes**
  - Preserved gateway state when uninstalling with `--keep-openshell`.
- Prevented conflicting messaging credentials from blocking onboarding
and rebuilds.
- Improved gateway diagnostics, dependency security, runtime filesystem
protection, and evidence handling.
- **Documentation**
  - Published the v0.0.98 release notes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@wscurran wscurran added area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression labels Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: sandbox OpenShell sandbox lifecycle, runtime, config, or recovery bug-fix PR fixes a bug or regression

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants