Skip to content

fix(sandbox): serialize live create handoff - #8729

Merged
apurvvkumaria merged 1 commit into
mainfrom
codex/serialize-live-create-handoff
Aug 10, 2026
Merged

fix(sandbox): serialize live create handoff#8729
apurvvkumaria merged 1 commit into
mainfrom
codex/serialize-live-create-handoff

Conversation

@apurvvkumaria

@apurvvkumaria apurvvkumaria commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

Live onboarding now waits for the OpenShell create client to release ownership before applying restart-safe Docker recreation. Previously the active onboarding path bypassed the existing ownership barrier, so recreation could race the still-running create process and leave fresh sandboxes unready.

Related Issue

Follow-up to #8720. This is complementary to the stopped-sandbox recovery change in #8728.

Changes

  • Reuse streamSandboxCreate's existing waitForReadyTermination barrier in the active unmanaged, non-compatibility restart-safe path.
  • Suppress the existing poll-time recreation in that path so the existing ensureApplied() cutover runs only after create ownership is released.
  • Tighten the existing no-GPU Docker-route test to cover the barrier, suppressed early patch, and deferred cutover without adding a new test file.
  • Leave stopped-sandbox recovery, timing thresholds, legacy upgrades, and MCP coverage unchanged.

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: This restores the documented onboarding-ready contract without changing commands, configuration, remediation, or intended output.
  • 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: The change only gates the existing restart-safe recreation on release of create-process ownership. Existing failure classification, managed lifecycle handling, compatibility recreation, rollback, and readiness checks remain unchanged.
  • Non-success, skipped, or missing CI check accepted by maintainer — check name, approval link, and follow-up issue:

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: no-docs-needed
  • Evidence: No documentation paths changed. Existing docs/reference/commands.mdx and docs/get-started/quickstart.mdx already own the unchanged create, ready, and dashboard contract.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

  • Tested on DGX Station
  • Tested commit:
  • Station profile/scenario:
  • Result:
  • Supporting evidence:

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 validate:pr passed after refreshing origin/main 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: npx vitest run --project cli src/lib/onboard/sandbox-gpu-create-flow.test.ts src/lib/sandbox/create-stream.test.ts (56 passed); npm run typecheck:cli passed.
  • Applicable broad gate passed — npm test for broad runtime/test-harness changes; npm run check for repo-wide validation/coverage changes — command/result: Not applicable; the change is a focused two-file onboarding sequencing fix covered by targeted tests and normal hooks.
  • 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: Apurv Kumaria akumaria@nvidia.com

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
@apurvvkumaria apurvvkumaria self-assigned this Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The native GPU sandbox creation flow now defers runtime patching for restart-safe no-GPU recreation until readiness termination. The test verifies persisted startup settings, readiness waiting, and patch application after create-process completion.

Changes

Restart-safe recreation

Layer / File(s) Summary
Deferred patch cutover
src/lib/onboard/sandbox-gpu-create-run-attempt.ts
The flow computes route-aware persistence flags. Eligible native attempts defer runtime patches and wait for readiness termination.
Cutover flow validation
src/lib/onboard/sandbox-gpu-create-flow.test.ts
The test captures the Docker GPU patch, verifies readiness waiting, and confirms patch application after process completion.

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

Possibly related issues

Possibly related PRs

  • NVIDIA/NemoClaw#8722 — Directly relates to the restart-safe Docker recreation handoff and deferred GPU patching.
  • NVIDIA/NemoClaw#8583 — Relates to Docker GPU patch cloning and startup-patch validation during recreation.
  • NVIDIA/NemoClaw#8058 — Shares readiness polling changes in the same sandbox creation flow and test files.

Suggested labels: area: sandbox

Suggested reviewers: cv, ericksoa

🚥 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 clearly and concisely describes the main change: serializing the live sandbox create handoff.
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 codex/serialize-live-create-handoff

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

@github-code-quality

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit b13bb57 in the codex/serialize-live... branch remains at 96%, unchanged from commit dfef83e in the main branch.

@apurvvkumaria
apurvvkumaria enabled auto-merge (squash) August 10, 2026 11:05

@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/onboard/sandbox-gpu-create-flow.test.ts`:
- Around line 539-549: Update the sandbox creation test around
streamSandboxCreate so its mock invokes the captured onPoll callback before the
stream promise resolves, rather than calling it afterward in the test body.
Assert the behavioral order of the poll, stream completion, and ensureApplied(),
while verifying maybeApplyDuringCreate() is skipped; avoid assertions that
depend on implementation-specific call structure.
🪄 Autofix

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: cebd8bbc-375e-47cd-84e3-f5a5e5878bf9

📥 Commits

Reviewing files that changed from the base of the PR and between dfef83e and b13bb57.

📒 Files selected for processing (2)
  • src/lib/onboard/sandbox-gpu-create-flow.test.ts
  • src/lib/onboard/sandbox-gpu-create-run-attempt.ts

Comment on lines +539 to +549
expect(mocks.streamSandboxCreate).toHaveBeenCalledWith(
"openshell",
["sandbox", "create"],
input.sandboxEnv,
expect.objectContaining({ waitForReadyTermination: true }),
);
const onPoll = mocks.streamSandboxCreate.mock.calls[0]?.[3]?.onPoll;
expect(onPoll).toBeTypeOf("function");
onPoll();
expect(patch.maybeApplyDuringCreate).not.toHaveBeenCalled();
expect(patch.ensureApplied).toHaveBeenCalledOnce();

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exercise onPoll before the stream resolves.

The explicit call at Line 547 occurs after the stream invocation in the test body. It does not prove that an active create poll skips maybeApplyDuringCreate() or that ensureApplied() runs after ownership release. Configure the stream mock to invoke onPoll before it resolves, then assert the order: poll, stream completion, ensureApplied().

As per path instructions, review tests for behavioral confidence rather than implementation lock-in.

🤖 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/onboard/sandbox-gpu-create-flow.test.ts` around lines 539 - 549,
Update the sandbox creation test around streamSandboxCreate so its mock invokes
the captured onPoll callback before the stream promise resolves, rather than
calling it afterward in the test body. Assert the behavioral order of the poll,
stream completion, and ensureApplied(), while verifying maybeApplyDuringCreate()
is skipped; avoid assertions that depend on implementation-specific call
structure.

Source: Path instructions

@apurvvkumaria
apurvvkumaria merged commit 273e521 into main Aug 10, 2026
74 of 76 checks passed
@apurvvkumaria
apurvvkumaria deleted the codex/serialize-live-create-handoff branch August 10, 2026 11:10
@github-actions github-actions Bot added the v0.0.106 Release target label Aug 10, 2026
@github-actions

github-actions Bot commented Aug 10, 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 terminology decisions differ; normalized E2E selections differ; Nemotron reported the same number of blockers, 1 more warning, the same number of suggestions.
3 additional E2E selections from the second opinion

Advisory only. The primary lane did not select these E2E jobs or targets.

  • gpu-e2e: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • sessions-agents-cli: The completed second-opinion lane identified E2E coverage that the primary lane omitted.
  • openshell-gateway-upgrade: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

Second-opinion terminology and E2E selections are advisory. Live E2E does not run automatically for pull requests.

2 semantic terminology decisions

Terminology decisions are advisory. They affect the assessment only when a separate finding identifies concrete semantic impact.

  • established — restart-safe at src/lib/onboard/sandbox-gpu-create-flow.test.ts:510: Keep `restart-safe`; repository lifecycle code already uses it for this persisted startup behavior.
  • established — cutover at src/lib/onboard/sandbox-gpu-create-run-attempt.ts:133: Keep `cutover`; repository lifecycle code uses it for controlled ownership transitions.

E2E guidance

Advisory only. A maintainer can dispatch the default E2E suite against this exact revision.

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

Workflow run details

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

apurvvkumaria added a commit that referenced this pull request Aug 10, 2026
<!-- markdownlint-disable MD041 -->
## Summary
Tests now exercise the serialized create handoff added by #8729 at the
actual lifecycle boundary. This also fixes the late shard-12 failure
where the integration fixture never reported that its fake create
process exited after `SIGTERM`.

## Related Issue
Follow-up to #8729 and its [CodeRabbit ordering
finding](#8729 (comment)).

## Changes
- Invoke the captured create poll before the mocked stream resolves and
assert the poll, stream completion, and deferred `ensureApplied()`
order.
- Make the existing process-group fixture emit the fake create child's
close event after `SIGTERM`, matching the ownership-release contract.
- Assert that the waited-for stream is not detached, with no
production-code changes or new test files.

## 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: Test fixtures now match the
already-merged ownership contract; no production behavior or user-facing
surface changes.
- [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: Test-only changes
preserve the fail-closed create timeout, simulate only the expected
process exit, and do not alter production lifecycle, rollback,
readiness, or compatibility behavior.
- [ ] Non-success, skipped, or missing CI check accepted by maintainer —
check name, approval link, and follow-up issue:

## Documentation Writer Review
<!-- Required for code and documentation changes after the changes and
applicable validation are complete. Keep one review checkbox and one
instance of each visible or hidden field. For Evidence, list changed
documentation paths. For documentation-only changes, also state that the
writing rules and documentation style were reviewed. For other results,
explain why no documentation change is needed or why the review is
blocked. For Agent, use a consistent product and surface name, such as
Codex Desktop, Codex CLI, Claude Code, or Cursor. After committing all
review changes, put `git rev-parse --short HEAD` and `git rev-parse
--short HEAD:AGENTS.md` in the hidden metadata below. Rerun the review
and refresh that metadata after any new commit. This receipt is advisory
during the data-collection pilot. -->
- [x] Documentation writer subagent reviewed the completed changes
- Result: `no-docs-needed`
- Evidence: No documentation paths changed. Existing
`docs/get-started/quickstart.mdx` and `docs/reference/commands.mdx`
already describe the unchanged ready and recreation contract.
- Agent: Codex Desktop
<!-- docs-review-head-sha: 70160ea -->
<!-- docs-review-agents-blob-sha: c4923a3 -->

## DGX Station Hardware Evidence
<!-- Required only when scripts/prepare-dgx-station-host.sh changes.
Maintainers must review the linked evidence before approving or merging.
This is human-reviewed evidence, not authenticated hardware provenance.
Exceptional bypasses use existing repository governance and must be
documented on the PR. -->
- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## 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 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 — command/result or justification: `npx
vitest run --project cli src/lib/onboard/sandbox-gpu-create-flow.test.ts
src/lib/sandbox/create-stream.test.ts` (56 passed); `npx vitest run
--project integration test/onboard-sandbox-recreation.test.ts -t "waits
for the create stream to close"` (1 passed).
- [ ] Applicable broad gate passed — `npm test` for broad
runtime/test-harness changes; `npm run check` for repo-wide
validation/coverage changes — command/result: Not applicable; this is a
two-test fixture correction protected by targeted tests and normal
hooks.
- [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

* **Tests**
* Improved coverage for restarting and recreating GPU-enabled sandboxes
safely.
* Verified that updates are applied only after sandbox creation
completes.
* Strengthened readiness and cleanup checks for sandbox creation
processes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

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

Labels

v0.0.106 Release target

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants