Skip to content

fix(rebuild): restart the Hermes gateway after state restore - #8472

Open
hunglp6d wants to merge 12 commits into
mainfrom
fix/rebuild-gateway-restart-after-restore
Open

fix(rebuild): restart the Hermes gateway after state restore#8472
hunglp6d wants to merge 12 commits into
mainfrom
fix/rebuild-gateway-restart-after-restore

Conversation

@hunglp6d

@hunglp6d hunglp6d commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

rebuild starts the sandbox gateway during recreation and restores durable workspace state about a minute later, so the gateway keeps serving the state it read before the restore replaced it. The post-restore step proved only that the gateway was alive — which was never in doubt — so rebuild reported success while the restored state was ignored. It now restarts the gateway after the restore and only reports health for a process that restart produced.

Before: rebuild finishes with a gateway older than the state it serves, and any adapter that reads its durable state once at startup keeps the pre-restore result until an operator runs nemoclaw <sandbox> gateway restart by hand. After: the gateway in a completed rebuild started after the restore.

Related Issue

Part of #8184, item 4. No closing keyword: #8184 is the umbrella report and its other items are fixed separately.

Changes

  • src/lib/actions/sandbox/rebuild-hermes-post-restore.tsensureHermesGatewayAfterStateRestore restarts the managed gateway once, then runs the existing bounded recheck loop. healthy now requires both that the restart succeeded and that the gateway is running; a gateway that stayed up through a failed restart is unverified, because it is still serving the state this step exists to replace. A gateway the recovery check replaced is still accepted as recovered — that process is new regardless of what the restart reported.
  • src/lib/actions/sandbox/rebuild-post-restore-phase.ts — success line now reads Hermes gateway restarted and verified after state restore.
  • docs/manage-sandboxes/recover-rebuild-sandboxes.mdx — the page summarizes the printed recovery guidance, so it names gateway restart first and recover as the fallback, and states why the restart is needed.
  • Tests: unit coverage for each branch, a rebuild-flow-harness test asserting restore → restart → health check ordering, an injectable restartSandboxGateway in the harness, and a live assertion in rebuild-hermes.test.ts that rebuild reports a gateway bound to the restored state.

The restart stays outside runHermesCronRestoreTransaction: that gate records the gateway pid and start_time when it drains dispatch and compares them again on validate and release, so a restart inside it would fail its own identity check.

No new abstraction, configuration, fallback, or compatibility path. The restart reuses the exported restartSandboxGateway.

This is not a new pattern. relaunchManagedSupervisorSession (supervisor-relaunch.ts) and restartRestoredSandboxGateway (restore-gateway-pairing.ts) already restart the gateway after their own restore, for the same reason. rebuild was the outlier.

main gained a separate fix for the same function while this branch was open — a bounded recheck around checkAndRecoverSandboxProcesses (HERMES_GATEWAY_RECHECK_ATTEMPTS). This branch merges it rather than replacing it: the recheck tolerates a check that comes back inconclusive, and the restart added here is what makes the observed process a fresh one. They address different failures and both are needed.

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:
  • 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: not yet accepted. PR review advisor (Nemotron 3 Ultra), cli-tests, cli-test-shards (5), and checks are failing on this head and need triage before review.

Documentation Writer Review

  • Documentation writer subagent reviewed the completed changes
  • Result: docs-updated
  • Evidence: docs/manage-sandboxes/recover-rebuild-sandboxes.mdx. The review returned one blocking finding — the page summarized the printed recovery guidance and still named recover for gateway health after the CLI message changed — and it was fixed in this change. The review ran at cc9a3dd250; this PR's own documentation diff is unchanged since then, so the result still describes the current content.
  • Agent: Claude Code

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: not re-run at this head. The live measurements below were taken at 46940cb2a5; the current head adds one further merge from main and has not been re-measured.
  • 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)

Live evidence

Measured four times, on three hosts, by three independent operators — my own run plus two verification agents given the same script on two freshly provisioned machines and no knowledge of each other's results. Each sandbox came from a real onboard --non-interactive run, not from seeded registry state. A marker file was written into the memories state directory before each rebuild so the restore had something to carry back.

ctime is the signal, not mtime: the restore preserves mtime, so a marker keeps its original value across rebuilds. Only ctime moves when the restore writes the file back.

Run Build Gateway start vs restore gateway-starts.log
1 main −67 s (before) 1 entry
2 main −27 s (before) 1 entry
3 main −49 s (before) 1 entry
1 this branch +6 s (after) 2 entries
2 this branch +9 s (after) 2 entries
3 this branch, clean checkout of 46940cb2a5, no local patches +9 s (after) 2 entries

The second gateway-starts.log entry makes the restart observable inside the sandbox rather than only in CLI output. On main the rebuild printed Hermes gateway health verified after state restore; on this branch it printed Hermes gateway restarted and verified after state restore, and neither of the other two states. Marker contents survived every rebuild, so the restore itself worked in each run.

Environments: Ubuntu 24.04, kernels 6.8 and 6.17, x86_64, Docker 29.7.2, OpenShell 0.0.85, Hermes Agent 0.19.0, Node 22.23.2, NVIDIA hosted inference.

Scope

Reproduced on Hermes. Not tested on OpenClaw, which has no equivalent post-restore gateway step — ensureHermesGatewayAfterStateRestore returns not-applicable for every other agent. The comment in supervisor-relaunch.ts names OpenClaw as retaining pre-restore runtime state on that path, so the same question is open for OpenClaw and is left for a separate change.

This change corrects the ordering between the gateway and the state it serves. It is not sufficient on its own to make a Hermes WhatsApp channel deliver messages; other defects in that path are tracked separately under #8184.

Merge-order note for #8423

PR #8423 adds a section to docs/manage-sandboxes/set-up-whatsapp.mdx instructing users to run gateway restart after rebuild, with the rationale this change removes. That text is not on main, so it cannot be removed here. Whichever of the two PRs merges second must delete the manual gateway restart line and the two sentences explaining it.


Signed-off-by: Hung Le hple@nvidia.com

Summary by CodeRabbit

  • Bug Fixes

    • Improved sandbox rebuild recovery by restarting the Hermes gateway after state restoration.
    • Added health verification after restart, with automatic recovery guidance when verification fails.
    • Clarified recovery status and messaging so successful rebuilds indicate the gateway was restarted or recovered.
  • Documentation

    • Updated recovery guidance to prioritize gateway restart, followed by recovery when necessary.
  • Tests

    • Added coverage for restart ordering, failure handling, recovery, and end-to-end rebuild verification.

Rebuild starts the gateway during recreation and restores durable state
about 27 seconds later. An adapter that reads its state once at startup
keeps the pre-restore result for the life of the process — Hermes' WhatsApp
bridge reads its paired session that way — so the gateway can be alive and
healthy while still serving the state the rebuild replaced.

The post-restore step proved only liveness, which was never in doubt, so it
reported success and left the channel unpaired until an operator ran
`gateway restart` by hand. Restart the gateway first and let the existing
check report on the process that restart produced. A gateway that stays up
through a failed restart is now unverified instead of healthy; one the
recovery check replaced is still accepted, because that process is new.

`relaunchManagedSupervisorSession` and `restartRestoredSandboxGateway`
already restart after their own restore, so rebuild was the outlier. The
restart stays outside `runHermesCronRestoreTransaction`, whose drain gate
compares the gateway pid and start time on validate and release.

Signed-off-by: Hung Le <hple@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 6, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: 9f1d2f0f-cdc7-4ea1-8a15-a6d3174a0edf

📥 Commits

Reviewing files that changed from the base of the PR and between 19b096b and a88afeb.

📒 Files selected for processing (8)
  • docs/manage-sandboxes/recover-rebuild-sandboxes.mdx
  • src/lib/actions/sandbox/rebuild-hermes-post-restore.test.ts
  • src/lib/actions/sandbox/rebuild-hermes-post-restore.ts
  • src/lib/actions/sandbox/rebuild-post-restore-phase.ts
  • test/e2e/live/rebuild-hermes.test.ts
  • test/helpers/rebuild-flow-harness.ts
  • test/helpers/rebuild-flow-test-harness.ts
  • test/helpers/rebuild-flow-test-support.ts

📝 Walkthrough

Walkthrough

Hermes rebuild recovery now restarts the gateway after state restoration, checks gateway health, and then completes MCP reconciliation. Tests cover ordering, restart failures, recovery outcomes, non-Hermes rebuilds, harness support, and end-to-end output.

Changes

Hermes rebuild recovery

Layer / File(s) Summary
Gateway restart and recovery flow
src/lib/actions/sandbox/rebuild-hermes-post-restore.ts, src/lib/actions/sandbox/rebuild-post-restore-phase.ts, docs/manage-sandboxes/recover-rebuild-sandboxes.mdx
Hermes post-restore handling restarts the gateway quietly before health checks. Recovery status prioritizes recovered processes, and messages describe the restart and verification sequence.
Restart dependency test wiring
test/helpers/rebuild-flow-harness.ts, test/helpers/rebuild-flow-test-harness.ts, test/helpers/rebuild-flow-test-support.ts
Rebuild-flow harnesses accept configurable gateway restart results and expose restart spies with successful defaults.
Restart ordering and output validation
src/lib/actions/sandbox/rebuild-hermes-post-restore.test.ts, test/e2e/live/rebuild-hermes.test.ts
Tests cover restart ordering, quiet mode, failed restarts, recovery replacement, non-Hermes behavior, and successful rebuild output.

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

Sequence Diagram(s)

sequenceDiagram
  participant StateRestore
  participant HermesPostRestore
  participant Gateway
  participant RecoveryCheck
  participant MCPReconciliation
  StateRestore->>HermesPostRestore: complete state restoration
  HermesPostRestore->>Gateway: restart gateway quietly
  Gateway-->>HermesPostRestore: restart result
  HermesPostRestore->>RecoveryCheck: verify or recover gateway
  RecoveryCheck-->>HermesPostRestore: gateway status
  HermesPostRestore->>MCPReconciliation: reconcile MCP configuration
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#8505: Uses the same post-restore phase while moving finalization logic and tests into that flow.

Suggested labels: area: sandbox, bug-fix

Suggested reviewers: apurvvkumaria, ericksoa

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 and concisely describes the main change: restarting the Hermes gateway after state restoration.
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 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/rebuild-gateway-restart-after-restore

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

@github-code-quality

github-code-quality Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit fee1792 in the fix/rebuild-gateway-... branch remains at 96%, unchanged from commit c31724f in the main branch.


Updated August 07, 2026 10:55 UTC

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Blocking findings reported

Advisor assessment: Blockers require maintainer review
Next action: Review the blockers below.
Findings: 1 blocker · 0 warnings · 0 suggestions

Model lanes

  • GPT-5.6 Terra (primary): Completed · high confidence · 1 blocker · 0 warnings · 0 suggestions
  • Nemotron 3 Ultra (second opinion): Failed after a partial review · low confidence · 1 blocker · 1 warning · 0 suggestions

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

3 semantic terminology decisions

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

  • established — gateway restart at docs/manage-sandboxes/recover-rebuild-sandboxes.mdx:227: Keep `gateway restart` for the named CLI operation.
  • established — restored state at docs/manage-sandboxes/recover-rebuild-sandboxes.mdx:225: Keep `restored state` for state applied by the rebuild restore.
  • established — durable state at src/lib/actions/sandbox/rebuild-hermes-post-restore.ts:88: Keep `durable state` where the persistence boundary distinguishes it from process memory.

E2E guidance

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

Recommended E2E: managed-image-multiarch-startup, managed-image-protected-runtime, onboard-repair, onboard-resume, rebuild-hermes, rebuild-hermes-stale-base, rebuild-openclaw, state-backup-restore

Blockers

PRA-1 Blocker — Keep the cron dispatch gate until the restored-state gateway is available

  • Location: src/lib/actions/sandbox/rebuild-pipeline.ts:483
  • Category: correctness
  • Problem: The rebuild releases the Hermes cron dispatch gate before the post-restore phase restarts the gateway. A cron job can dispatch in that interval through the recreated gateway process that loaded state before restoration.
  • Impact: A restored cron job can run with pre-restore gateway state, violating the rebuild guarantee that restored Hermes state is active before dispatch resumes.
  • Fix: Reorder or extend the cron restore protocol so dispatch remains blocked until post-restore gateway restart or recovery establishes a process bound to restored state, while preserving the receipt identity validation.
  • Verification: Trace runHermesCronRestoreTransaction in rebuild-pipeline.ts:483 through runRebuildPostRestorePhase, then compare its release call in rebuild-hermes-post-restore.ts:390-409 with the restart at rebuild-post-restore-phase.ts:252-255.
  • Test coverage: Add a deterministic rebuild test that records cron-gate release, gateway replacement, and a dispatch attempt, and proves dispatch remains blocked until the replacement is verified.
  • Evidence: src/lib/actions/sandbox/rebuild-pipeline.ts:483-496 invokes runHermesCronRestoreTransaction before runRebuildPostRestorePhase. src/lib/actions/sandbox/rebuild-hermes-post-restore.ts:390-409 validates and releases the dispatch gate before returning. src/lib/actions/sandbox/rebuild-post-restore-phase.ts:252-255 invokes the new post-restore gateway check, which restarts Hermes.

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: Apurv Kumaria <akumaria@nvidia.com>
@apurvvkumaria

Copy link
Copy Markdown
Collaborator

The two failing CLI shards were caused by this change: the older shared rebuild-flow harness did not stub the newly required Hermes gateway restart, so otherwise successful rebuild cases reached the real restart path and failed post-restore verification.

I added the same successful restart stub and typed override/spy already used by the newer harness. Validation now passes for the 111 rebuild-flow cases and the previously failing base-image case; CLI type-check and Biome checks also pass. An independent documentation review confirmed that the existing sandbox recovery page already covers the user-visible behavior and that this test-helper repair needs no further docs change.

@copy-pr-bot

copy-pr-bot Bot commented Aug 6, 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.

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Maintainer update on the requested change:

  • Restored the bounded Hermes gateway recheck count used by the new post-restore loop. Its accidental deletion caused the reported CLI parity compile failure (TS2304); the current branch revision (46940cb2a) builds and type-checks successfully.
  • Preserved the contributor's commits and normal branch history. The contributor had already integrated current main; the follow-up was pushed normally without rewriting the branch.
  • Validation passed: Hermes post-restore tests 19/19, post-restore phase tests 10/10, complete rebuild-flow tests 111/111, affected base-image flow 1/1, CLI/plugin builds, CLI type-check, all applicable repository hooks, and the documentation build (0 errors; 2 pre-existing warnings).
  • Two failures seen during one concurrent local run were shared-host timeout artifacts: the gateway-down refusal case and recorded base-image-hint case each passed independently in 2.4–2.7 seconds, and the complete rebuild-flow suite passed.
  • The independent documentation review passed with no edits. It confirmed the Hermes-only scope, restore → restart → health/recovery ordering, printed recovery guidance, and the merge-order note for fix(messaging): let the operator choose the Hermes WhatsApp mode #8423.
  • The nine-category sensitive-path review passed with no findings. This reuses existing registry- and supervisor-scoped controls, adds no credential, dependency, network-policy, cryptography, or storage surface, and continues to fail closed when restart or recovery cannot prove a post-restore process.

The earlier CLI parity failure was PR-related and is fixed. Setup-stage failures from the GitHub Actions outage were infrastructure failures and were not rerun; fresh checks are now queued for the updated branch.

The PR remains draft. It still needs contributor ready-state intent, green required checks, and an independent human approval before it can merge.

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

CI follow-up:

  • cli-test-shards (5) passed on the failed-only rerun; the aggregate cli-tests and checks jobs passed as well.
  • The original shard failure contained two timeouts in unchanged areas: the Linux-only managed-bootstrap static-link inspection and the NIM nonexistent-container status probe. The NIM probe passed three consecutive local repetitions, and the focused Hermes post-restore cases passed 5/5. No branch change was needed.
  • The secondary review-advisor rerun also passed. All visible checks are now successful or appropriately skipped.

The PR remains draft because contributor ready-state intent and independent human approval are still outstanding.

@apurvvkumaria

Copy link
Copy Markdown
Collaborator

Maintainer follow-up after the branch's latest main refresh:

  • The effective eight-file change is unchanged and mergeable. No unresolved review threads or submitted change requests were found.
  • The required CI aggregate, all CLI shards, DCO, commit verification, documentation receipt, preview/parity checks, CodeQL, and security scans pass.
  • One untouched lifecycle-lock test hit a 40 ms timing race on the first run. The failed shard and aggregate gates passed on a targeted retry, confirming a transient test failure.
  • The optional Nemotron advisor lane failed again after one bounded retry because its model output could not be parsed. The primary advisor and publish job pass, so this is not a source or test failure.
  • All non-merge commits carry DCO sign-off and all commits are GitHub Verified. The documentation review and nine-category sensitive-path review have no findings.
  • Main subsequently advanced by two commits in disjoint files; no overlap with this change was found.

No further technical, documentation, compliance, or security change is indicated. The PR remains draft. Remaining blockers are the contributor's decision to mark it ready and independent human approval.

cv
cv previously requested changes Aug 7, 2026

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

This PR remains a draft and is behind the current main commit. Refresh it, complete the Hermes post-restore lifecycle evidence, and run the required workflows before marking it ready. The restart-before-health contract correctly avoids accepting the pre-restore gateway process, and the current advisor reports no additional finding.

@cv
cv dismissed their stale review August 7, 2026 10:33

The stale-base request was addressed. Draft state and required checks remain separate from code-review findings.

@hunglp6d
hunglp6d marked this pull request as ready for review August 7, 2026 10:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants