Skip to content

fix(rebuild): reconcile stale pinned session models after inference switch (#7102) - #7109

Merged
apurvvkumaria merged 7 commits into
mainfrom
fix/7102-reconcile-stale-session-model-on-rebuild
Jul 17, 2026
Merged

fix(rebuild): reconcile stale pinned session models after inference switch (#7102)#7109
apurvvkumaria merged 7 commits into
mainfrom
fix/7102-reconcile-stale-session-model-on-rebuild

Conversation

@yanyunl1991

@yanyunl1991 yanyunl1991 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Summary

After nemoclaw inference set + rebuild, the first nemoclaw connect session shows the old model name in the OpenClaw TUI status bar; a disconnect + reconnect shows the correct new name. This PR reconciles the stale per-session model state during rebuild so the first connect shows the new model.

Closes #7102.

Reproduction

On our Ubuntu 24.04 x86_64 test host (no GPU), against a managed-inference sandbox (the status-bar model uses the inference/<model> managed ref regardless of the concrete provider):

  1. Onboard a sandbox with model A.
  2. Use the model once (so OpenClaw persists a session — agent:main:main — pinned to A). The reporter's QA flow does this by chatting before switching.
  3. nemoclaw inference set --provider <p> --model <B>
  4. nemoclaw <sb> rebuild --yes
  5. nemoclaw <sb> connect then openclaw tui — observe the status-bar model.

Observed on main (before fix) — first connect shows the OLD model:

agent main | session main | inference/<A>  | tokens ?/131k     <-- OLD (pre-switch)
# on-disk config agents.defaults.model.primary = inference/<B> (NEW)
# sessions.json agent:main:main -> { modelProvider: "inference", model: "<A>" }  (stale)

Observed on fix/... (after fix) — first connect shows the NEW model:

agent main | session main | inference/<B>  | tokens ?/131k     <-- NEW
# sessions.json agent:main:main -> pin cleared -> follows config default (B)

Analysis

OpenClaw pins a { modelProvider, model } on each stored session in /sandbox/.openclaw/agents/<id>/sessions/sessions.json (visible via openclaw status → the per-session Model column). nemoclaw inference set only rewrites the OpenClaw config (agents.defaults.model.primary in openclaw.json, via patchOpenClawInferenceConfig/writeSandboxConfig), and rebuild restores the agents/ state dir (including sessions.json) verbatim — neither reconciles the per-session pinned model. The OpenClaw TUI resumes the last session on connect and renders that session's pinned model, so the first connect after a switch shows the pre-switch model. There is no OpenClaw-native "set session model" command; the only native lever (sessions.reset) requires a live gateway.

Fix

Reconcile the persisted pins during the rebuild post-restore window (rebuild-post-restore-phase.ts, right after openclaw doctor --fix), while the gateway is still down — OpenClaw owns sessions.json while live, so editing it during inference set would race its writes; the post-restore window does not, and the reporter's inference setrebuildconnect flow always passes through it.

Contract (reconcilePinnedSessionModels, pure + unit-tested): for the default agent's session store, clear the pin (model + modelProvider) of any session whose modelProvider is the managed provider (inference) and whose inference/<model> no longer equals the current agents.defaults.model.primary. Cleared sessions fall back to the config default (OpenClaw's own clean-entry semantics after sessions.reset). Sessions already on the default, and sessions pinned to a different provider (an intentional per-session choice), are left untouched.

Changes

  • src/lib/actions/sandbox/reconcile-session-models.ts: new — pure reconcilePinnedSessionModels contract + reconcileStalePinnedSessionModelsAfterRebuild (reads the restored primary + session store, writes back only if stale pins were cleared).
  • src/lib/actions/sandbox/rebuild-post-restore-phase.ts: invoke the reconcile in the openclaw post-restore window.
  • src/lib/actions/sandbox/reconcile-session-models.test.ts: new — locks the contract (clears stale managed pins; leaves current/other-provider/unpinned sessions and malformed/missing input alone).

Type of Change

  • Code change (feature, bug fix, or refactor)

Verification

  • Unit tests for the reconcile contract pass (reconcile-session-models.test.ts)
  • npm run typecheck:cli and npm run build:cli pass
  • Reproduced end-to-end on our Ubuntu 24.04 x86_64 test host: before the fix the first connect's TUI status bar showed the old model; after the fix, the rebuild clears the stale pins and the first connect shows the new model.
  • No secrets, API keys, or credentials committed

AI Disclosure

  • AI-assisted — tool: Claude Code

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

Summary by CodeRabbit

  • Bug Fixes

    • Improved restore-and-rebuild handling to reconcile stale managed pinned session model/provider selections after the sandbox doctor step.
    • Automatically clears only outdated managed pins while preserving the rest of each session entry, leaving intentionally non-managed pins untouched.
    • Updates the session store using a race-resistant, atomic file replacement approach with safer skip/failure behavior when prerequisites aren’t satisfied.
  • Tests

    • Added coverage for pinned-session reconciliation logic and atomic session-store replacement safeguards (including symlink and stale-content refusal cases).
    • Added rebuild post-restore flow tests to verify correct ordering and agent scoping.

…witch (#7102)

OpenClaw pins a `{ modelProvider, model }` on each stored session in
`agents/<id>/sessions/sessions.json`. `nemoclaw inference set` + `rebuild`
update the config default (`agents.defaults.model.primary`) but leave those
per-session pins on the pre-switch model. When the OpenClaw TUI resumes the
last session on the first `connect` after a switch, its status bar shows the
old pinned model; a reconnect looks correct once the session is reconciled.

Reconcile the persisted pins during the rebuild post-restore window, while the
gateway is down (OpenClaw owns `sessions.json` while live, so editing it there
would race its writes). For the default agent, clear the pin of any session
whose managed-`inference` model no longer matches the current default so it
falls back to the config default — matching OpenClaw's own clean-entry
semantics after `sessions.reset`. Sessions already on the default, and sessions
pinned to a different provider (an intentional per-session choice), are left
untouched.

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

coderabbitai Bot commented Jul 17, 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

Adds reconciliation for stale managed-provider session model pins after sandbox rebuilds, atomically persists cleared pins, logs outcomes, and invokes the process after openclaw doctor --fix.

Changes

Session model reconciliation

Layer / File(s) Summary
Session pin reconciliation and atomic replacement
src/lib/actions/sandbox/reconcile-session-models.ts, src/lib/actions/sandbox/reconcile-session-models.test.ts
Adds reconciliation results, clears stale managed-provider pins, implements guarded atomic replacement, preserves unaffected entries, and tests success and failure cases.
Sandbox rebuild persistence
src/lib/actions/sandbox/reconcile-session-models.ts, src/lib/actions/sandbox/reconcile-session-models.test.ts
Reads and validates the configured primary model, reconciles the default-agent session store, atomically writes changed content, and logs skip or failure outcomes.
Post-restore rebuild integration
src/lib/actions/sandbox/rebuild-post-restore-phase.ts, src/lib/actions/sandbox/rebuild-post-restore-phase.test.ts
Runs reconciliation after doctor repair for OpenClaw and verifies ordering and agent scoping.

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

Sequence Diagram(s)

sequenceDiagram
  participant runRebuildPostRestorePhase
  participant reconcileStalePinnedSessionModelsAfterRebuild
  participant executeSandboxCommand
  participant sessions.json
  runRebuildPostRestorePhase->>reconcileStalePinnedSessionModelsAfterRebuild: Reconcile after openclaw doctor --fix
  reconcileStalePinnedSessionModelsAfterRebuild->>executeSandboxCommand: Read primary model and sessions.json
  executeSandboxCommand-->>reconcileStalePinnedSessionModelsAfterRebuild: Return sandbox data
  reconcileStalePinnedSessionModelsAfterRebuild->>reconcilePinnedSessionModels: Clear stale managed pins
  reconcileStalePinnedSessionModelsAfterRebuild->>executeSandboxCommand: Atomically replace sessions.json
  executeSandboxCommand->>sessions.json: Guarded write
Loading

Possibly related PRs

  • NVIDIA/NemoClaw#7117: Both changes modify post-restore rebuild control flow in runRebuildPostRestorePhase.

Suggested labels: area: sandbox, area: inference, area: security

Suggested reviewers: jyaunches

🚥 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 matches the main change: reconciling stale session model pins after rebuild.
Linked Issues check ✅ Passed The changes address #7102 by clearing stale managed session model pins during rebuild so the next connect uses the updated primary model.
Out of Scope Changes check ✅ Passed The added atomic replace helper and tests support the same rebuild-time session-store reconciliation and do not appear unrelated.
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
  • Commit unit tests in branch fix/7102-reconcile-stale-session-model-on-rebuild

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

@github-code-quality

github-code-quality Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage remains at 96%, unchanged from the main branch.

TypeScript / code-coverage/cli

The overall coverage in the fix/7102-reconcile-s... branch remains at 80%, unchanged from the main branch.

Show a code coverage summary of the most impacted files.
File main e7e8b67 fix/7102-reconcile-s... 05965bb +/-
src/lib/core/pr...mpt-activity.ts 92% 67% -25%
src/lib/credentials/store.ts 64% 59% -5%
src/lib/actions...estore-phase.ts 91% 87% -4%
src/lib/actions...ssions/paths.ts 100% 96% -4%
src/lib/adapter...hell/resolve.ts 100% 100% 0%
src/lib/agent/defs.ts 81% 81% 0%
src/lib/agent/s...store-reader.ts 90% 90% 0%
src/lib/sandbox...rce-identity.ts 91% 91% 0%
src/lib/state/registry.ts 83% 86% +3%
src/lib/actions...ssion-models.ts 0% 89% +89%

Updated July 17, 2026 20:30 UTC
Code Coverage is in Public Preview. Learn more and provide us with your feedback.

@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

PR Review Advisor — Informational

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

Model lanes

  • GPT-5.6 Terra (primary): Completed · medium confidence · 0 blockers · 2 warnings · 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, 2 fewer warnings, 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, state-backup-restore, upgrade-stale-sandbox

3 optional E2E recommendations
  • openclaw-inference-switch
  • rebuild-openclaw
  • sandbox-rebuild
2 warnings · 0 suggestions

Warnings

Warnings do not block.

PRA-1 Warning — Prove the rebuild workaround against its originating inference-set state

  • Location: src/lib/actions/sandbox/reconcile-session-models.ts:245
  • Category: correctness
  • Problem: The best-effort post-restore workaround documents that `inference set` changes the config while rebuild restores a session-store pin, but the checked-in tests construct config and session JSON independently. They do not establish that the supported inference-set plus backup/restore path creates and preserves the stale pin that this recovery is intended to correct.
  • Impact: A change to inference-set or restore behavior could silently invalidate the workaround while its isolated unit tests remain green, leaving first-connect sessions on the old model or clearing pins under a state no longer produced by the supported flow.
  • Recommendation: Add a focused rebuild-flow regression that performs or faithfully crosses the inference-set and restore boundaries, demonstrates the stale managed pin surviving into post-restore state, and verifies it is cleared while a non-managed pin remains unchanged.
  • Verification: Inspect the existing rebuild pipeline/restore tests alongside reconcile-session-models.test.ts; confirm whether any test derives the reconciler input from an inference-set update followed by restored agents state.
  • Test coverage: A rebuild integration/flow test: switch the managed default through inference set, restore a session store containing the prior managed pin, run post-restore reconciliation, then assert the pin is removed and an explicit non-managed-provider pin is preserved.
  • Evidence: src/lib/actions/sandbox/reconcile-session-models.ts:245-250 describes a recovery for pins left by inference set and preserved by rebuild restore. src/lib/actions/sandbox/reconcile-session-models.test.ts constructs `config` and `staleStore` fixtures directly rather than traversing inference set or restore. The linked issue's observable expected behavior is that the first connection after inference set plus rebuild reflects the new model.

PRA-2 Warning — Cover retry after a guarded session-store write failure

  • Location: src/lib/actions/sandbox/reconcile-session-models.test.ts:335
  • Category: tests
  • Problem: The failure-path test verifies that one failed atomic write does not claim success or retry within that invocation, but it does not verify that a later rebuild/post-restore invocation can safely reconcile the same stale pin after the transient failure.
  • Impact: A persistent cleanup/staging or state-handling defect could make the recovery permanently skip its correction after one failed write, violating the rebuild lifecycle expectation that failed mutations remain retryable without destructive cleanup.
  • Recommendation: Add a test that makes the first guarded write fail, then invokes reconciliation again with the same restored config/store and a successful write result; assert only the second call reports reconciliation and dispatches the guarded replacement.
  • Verification: Inspect reconcile-session-models.test.ts around the existing atomic-write-failure test; confirm it ends after one invocation and has no subsequent successful retry assertion.
  • Test coverage: Mock config read and stale store read for two invocations, return a nonzero write status first and zero second, then assert the second invocation writes the stale source replacement and logs the cleared-session result without altering unrelated session entries.
  • Evidence: src/lib/actions/sandbox/reconcile-session-models.test.ts has an atomic write failure test that invokes reconcileStalePinnedSessionModelsAfterRebuild once. src/lib/actions/sandbox/reconcile-session-models.ts returns after a nonzero write status, leaving retryability to a later invocation. The deterministic risk plan requires failed upgrade/rebuild mutations to remain retryable without destructive cleanup.

Workflow run details

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

@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/actions/sandbox/reconcile-session-models.ts`:
- Around line 115-120: Update the sessions.json publish flow around
executeSandboxCommand to use the repository’s descriptor-safe temporary-file and
atomic-replace primitive instead of shell redirection to tmpPath followed by mv.
Ensure the write cannot follow a pre-existing symlink and that the replacement
preserves the original file’s owner and mode.
🪄 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: 995c0a0c-28a1-4eed-8def-aee151619fca

📥 Commits

Reviewing files that changed from the base of the PR and between b37e142 and 26f5d5d.

📒 Files selected for processing (3)
  • src/lib/actions/sandbox/rebuild-post-restore-phase.ts
  • src/lib/actions/sandbox/reconcile-session-models.test.ts
  • src/lib/actions/sandbox/reconcile-session-models.ts

Comment thread src/lib/actions/sandbox/reconcile-session-models.ts Outdated
@wscurran wscurran added area: cli Command line interface, flags, terminal UX, or output area: ui Web UI, terminal display, visual layout, or UX behavior bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior labels Jul 17, 2026
Replace restored session state through a no-follow, inode-checked atomic write.
Preserve the original owner and mode, refuse symlinked or concurrently changed stores,
and clean up owned staging files on failure.

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

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

🧹 Nitpick comments (2)
src/lib/actions/sandbox/reconcile-session-models.test.ts (2)

105-120: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test safety behavior rather than Python source text.

These assertions lock the test to os.* calls and a temporary-name implementation. Keep observable checks—rejection, metadata preservation, and no staging artifacts—and remove command substring assertions.

As per path instructions, “Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions.”

🤖 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/reconcile-session-models.test.ts` around lines 105 -
120, Update the buildSessionStoreReplaceCommand test to exercise the public
command behavior rather than asserting Python source substrings. Replace the
os.* and temporary-name checks with observable assertions covering rejection,
preservation of target metadata, atomic replacement, and cleanup of staging
artifacts; retain the existing test inputs and public boundary.

Source: Path instructions


132-136: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Keep host-process execution out of this unit test. These cases invoke real sh and python3; inject/mock the process boundary here and place the end-to-end shell/Python contract in an appropriate integration/E2E suite.

  • src/lib/actions/sandbox/reconcile-session-models.test.ts#L132-L136: replace the real process invocation with a mocked process boundary.
  • src/lib/actions/sandbox/reconcile-session-models.test.ts#L159-L166: move the symlink behavior check to integration/E2E coverage.
  • src/lib/actions/sandbox/reconcile-session-models.test.ts#L183-L190: move the stale-source behavior check to integration/E2E coverage.

As per coding guidelines, “Mock external dependencies in unit tests.”

🤖 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/reconcile-session-models.test.ts` around lines 132 -
136, The unit test currently executes real sh and python3 processes. In
src/lib/actions/sandbox/reconcile-session-models.test.ts lines 132-136, mock or
inject the process boundary used by buildSessionStoreReplaceCommand instead of
calling spawnSync directly; move the symlink behavior coverage at lines 159-166
and stale-source behavior coverage at lines 183-190 to an appropriate
integration/E2E suite, with no direct change required there beyond removal from
this unit test.

Source: Coding guidelines

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

Nitpick comments:
In `@src/lib/actions/sandbox/reconcile-session-models.test.ts`:
- Around line 105-120: Update the buildSessionStoreReplaceCommand test to
exercise the public command behavior rather than asserting Python source
substrings. Replace the os.* and temporary-name checks with observable
assertions covering rejection, preservation of target metadata, atomic
replacement, and cleanup of staging artifacts; retain the existing test inputs
and public boundary.
- Around line 132-136: The unit test currently executes real sh and python3
processes. In src/lib/actions/sandbox/reconcile-session-models.test.ts lines
132-136, mock or inject the process boundary used by
buildSessionStoreReplaceCommand instead of calling spawnSync directly; move the
symlink behavior coverage at lines 159-166 and stale-source behavior coverage at
lines 183-190 to an appropriate integration/E2E suite, with no direct change
required there beyond removal from this unit test.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: d4bbddda-c32f-4e99-a39b-ca25f7493a3f

📥 Commits

Reviewing files that changed from the base of the PR and between 26f5d5d and 520d3c0.

📒 Files selected for processing (2)
  • src/lib/actions/sandbox/reconcile-session-models.test.ts
  • src/lib/actions/sandbox/reconcile-session-models.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/actions/sandbox/reconcile-session-models.ts

Comment thread src/lib/actions/sandbox/reconcile-session-models.test.ts Fixed
Signed-off-by: Julie Yaunches <jyaunches@nvidia.com>

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

🧹 Nitpick comments (1)
src/lib/actions/sandbox/reconcile-session-models.test.ts (1)

238-241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep shell hardening assertions in the command-builder tests.

Checking os.O_NOFOLLOW and temporary-file names couples this orchestration test to generated source text without proving behavior. The dedicated replacement-command tests already own those guarantees; here, retain only the dispatch and outcome assertions.

Proposed cleanup
-    const writeCommand = executeSandboxCommandMock.mock.calls[2][1];
-    expect(writeCommand).toContain("python3 -c");
-    expect(writeCommand).toContain("os.O_NOFOLLOW");
-    expect(writeCommand).not.toContain(".nemoclaw-tmp");

As per path instructions, “Prefer observable outcomes through the public boundary over source-text, private-shape, or mock-call assertions.”

🤖 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/reconcile-session-models.test.ts` around lines 238 -
241, Remove the generated-command string assertions for “python3 -c”,
“os.O_NOFOLLOW”, and “.nemoclaw-tmp” from the reconciliation test. Keep this
orchestration test focused on dispatch and observable outcome assertions,
leaving shell-hardening coverage to the dedicated replacement-command tests.

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.

Nitpick comments:
In `@src/lib/actions/sandbox/reconcile-session-models.test.ts`:
- Around line 238-241: Remove the generated-command string assertions for
“python3 -c”, “os.O_NOFOLLOW”, and “.nemoclaw-tmp” from the reconciliation test.
Keep this orchestration test focused on dispatch and observable outcome
assertions, leaving shell-hardening coverage to the dedicated
replacement-command tests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 51612216-9632-4252-8b15-5c8927ef1e8d

📥 Commits

Reviewing files that changed from the base of the PR and between 520d3c0 and b4378e9.

📒 Files selected for processing (1)
  • src/lib/actions/sandbox/reconcile-session-models.test.ts

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

@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/actions/sandbox/reconcile-session-models.test.ts`:
- Around line 223-227: Update the buildSessionStoreReplaceCommand call in the
symlink reconciliation test to pass the exact original fixture content for hash
calculation, replacing original.trim() with original while leaving the
newline-terminated replacement content unchanged.
🪄 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: 72609c49-4c2a-4080-8f0f-2d665e5171e7

📥 Commits

Reviewing files that changed from the base of the PR and between 16a7fe4 and d0889ea.

📒 Files selected for processing (3)
  • src/lib/actions/sandbox/rebuild-post-restore-phase.test.ts
  • src/lib/actions/sandbox/reconcile-session-models.test.ts
  • src/lib/actions/sandbox/reconcile-session-models.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/lib/actions/sandbox/reconcile-session-models.ts

Comment on lines +223 to +227
buildSessionStoreReplaceCommand(
join(linkedParent, "sessions.json"),
'{"replace":true}\n',
original.trim(),
),

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

Hash the exact fixture content in this symlink test.

original.trim() differs from the file’s newline-terminated content, so the command may reject the stale hash before testing the symlinked parent path. Pass original to ensure this test exercises its stated claim.

Proposed fix
-            original.trim(),
+            original,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
buildSessionStoreReplaceCommand(
join(linkedParent, "sessions.json"),
'{"replace":true}\n',
original.trim(),
),
buildSessionStoreReplaceCommand(
join(linkedParent, "sessions.json"),
'{"replace":true}\n',
original,
),
🤖 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/reconcile-session-models.test.ts` around lines 223 -
227, Update the buildSessionStoreReplaceCommand call in the symlink
reconciliation test to pass the exact original fixture content for hash
calculation, replacing original.trim() with original while leaving the
newline-terminated replacement content unchanged.

Source: Path instructions

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

Reviewed the rebuild reconciliation and hardening changes. The stale managed session-pin fix is narrowly scoped; atomic replacement rejects symlink traversal and stale-source races, preserves metadata, and sanitizes sandbox-derived model references. Focused unit/orchestration coverage, full CI, security scans, advisor review, and the trusted exact-diff E2E gate (including upgrade-stale-sandbox) are green.

@apurvvkumaria
apurvvkumaria merged commit f1270ec into main Jul 17, 2026
52 checks passed
@apurvvkumaria
apurvvkumaria deleted the fix/7102-reconcile-stale-session-model-on-rebuild branch July 17, 2026 21:01
@jyaunches jyaunches mentioned this pull request Jul 18, 2026
21 tasks
apurvvkumaria pushed a commit that referenced this pull request Jul 18, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Add the v0.0.87 changelog entry and align the DGX Station,
platform-support, and rebuild documentation with behavior merged since
v0.0.86.
The Station documentation retains the Deferred support status while
recording the two exact factory-image qualification profiles and the
post-reboot receipt compatibility fix from #7130.

## Changes

- Add the v0.0.87 changelog summary, including the merged Station resume
receipt fix, with links to the owning documentation pages.
- Document the exact April 2026 Colossus BaseOS and June 2026 AI
Developer Tools Station identities, validation boundaries, and permitted
host preparation.
- Synchronize those Station qualification paths into the canonical
platform matrix and generated provider/platform pages.
- Document how an OpenClaw rebuild clears stale managed-provider
session-model pins after an inference switch.

### Source summary

- [#7130](#7130) ->
`docs/changelog/2026-07-17.mdx`: Document compatibility with current
six-field and legacy three-field Station resume receipts after host
preparation.
- [#7128](#7128) ->
`docs/changelog/2026-07-17.mdx`: Document restart-safe managed DCode
startup and required Docker resource limits.
- [#7126](#7126) ->
`docs/changelog/2026-07-17.mdx`,
`docs/get-started/dgx-station-preparation.mdx`,
`ci/platform-matrix.json`: Document the two bounded Station
factory-image qualification profiles without promoting Deferred support
and synchronize the generated platform/provider references.
- [#6947](#6947) ->
`docs/changelog/2026-07-17.mdx`: Document streaming sandbox backup
archive creation.
- [#7117](#7117) ->
`docs/changelog/2026-07-17.mdx`: Document Hermes post-restore gateway
and managed MCP health verification.
- [#7109](#7109) ->
`docs/changelog/2026-07-17.mdx`,
`docs/manage-sandboxes/recover-rebuild-sandboxes.mdx`: Document stale
managed session-model pin reconciliation after rebuild.
- [#7068](#7068) ->
`docs/changelog/2026-07-17.mdx`: Document strict-provider compatibility
for Hermes tool schemas.
- [#6965](#6965) ->
`docs/changelog/2026-07-17.mdx`: Document managed vLLM download storage
estimation.
- [#7114](#7114) ->
`docs/changelog/2026-07-17.mdx`: Document preserved, redacted rebuild
diagnostics.

## 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
- [ ] Existing tests cover changed behavior — justification:
- [x] Tests not applicable — justification: Documentation-only
release-prep update; the changelog, platform-generation contracts, and
docs build validate the changed pages and links.
- [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

- [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 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 — `npx vitest run
test/generate-platform-docs.test.ts test/station-doc-ownership.test.ts
test/changelog-docs.test.ts`: 29 passed; `python3
scripts/generate-platform-docs.py --check`: all generated tables in sync
- [ ] 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
- [x] `npm run docs` builds without warnings (doc changes only)
- [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)

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


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

- **New Features**
- Added filesystem-aware managed vLLM storage preflight (cold download
sizing; interactive vs non-interactive capacity checks).
- Improved tool-schema compatibility for strict OpenAI-compatible
providers (including Gemini schema handling) using a strict single
envelope.
- Enhanced sandbox backup creation with streamed archive generation and
incremental entry validation.
- **Bug Fixes**
- Strengthened rebuild/recovery checks with Hermes sandbox health
validation and cleanup of stale managed-provider session pins.
- Persisted onboarding startup commands with required `nproc`/`nofile`
limits across sandbox recreation.
- Improved replacement-image rebuild diagnostics with bounded, redacted
output handling.
- For OpenCLAW “rebuild while preserving state,” stale model/provider
pins are cleared when appropriate.
- **Documentation**
- Expanded DGX Station GB300 no-OTA factory profile/qualification
criteria and clarified managed vLLM provider/sandbox constraints.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

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

Labels

area: cli Command line interface, flags, terminal UX, or output area: ui Web UI, terminal display, visual layout, or UX behavior bug-fix PR fixes a bug or regression integration: openclaw OpenClaw integration behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Ubuntu 24.04][CLI&UX] TUI shows stale model name on first connect after nemoclaw inference set + rebuild

5 participants