Skip to content

feat(rebuild): add atomic managed workload replacement - #8001

Merged
ericksoa merged 81 commits into
mainfrom
feat/managed-workload-rebuild-parity
Aug 1, 2026
Merged

feat(rebuild): add atomic managed workload replacement#8001
ericksoa merged 81 commits into
mainfrom
feat/managed-workload-rebuild-parity

Conversation

@ericksoa

@ericksoa ericksoa commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds the inert, provider-neutral managed-workload rebuild transaction for the incremental buildless stack. The exact old workload and registry row remain authoritative through replacement preparation, readiness, state restore, and provider rebind. Only one exact compare-and-swap publishes the replacement, and old-runtime retirement happens afterward through provider-owned opaque handles.

This slice does not wire a production rebuild caller or activate buildless onboarding. Snapshot/backup and durable recovery ownership remain tracked in #7744 and are required before activation.

Related Issue

Part of #7744

Changes

  • Capture a deep-frozen rebuild plan bound to the exact provider, shipped agent, platform, prior managed receipt, full durable-row revision, lifecycle generation, and live identity fingerprint.
  • Pre-render and validate the exact replacement image, startup profile, receipt, and safe metadata before provider mutation.
  • Define provider-neutral prepare, create, readiness, restore, provider-rebind, rollback, abort-preparation, and retire-previous phases using opaque exact handles rather than sandbox-name deletion.
  • Keep partial prepare/create cleanup transaction-idempotent and run abort cleanup even when post-prepare registry revalidation throws.
  • Publish only through exact old-authority CAS; reconcile ambiguous persistence against either the exact replacement or exact old row.
  • Preserve the staged replacement and return an immutable recovery task when publication is indeterminate, avoiding rollback of a replacement that may already be durable.
  • Retire the exact old runtime only after publication; return a durable-owner recovery task if retirement remains pending.
  • Bind replacement contracts and startup profiles to OpenClaw, Hermes, or DCode authority and reject provider, agent, platform, receipt, generation, or identity drift.
  • Reject malformed provider artifacts at every transition, stop before later phases, and prove exact transaction abort or exact staged-handle rollback.
  • Document the shared backup boundary and the durable recovery ownership tracked in [Epic] Support native Podman with buildless managed onboarding #7744 before activation.

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: The transaction is inert with no production caller or support claim; the internal README records ownership boundaries for later slices.
  • 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: Exact-head audit covers immutable authority, pre-mutation validation, CAS ambiguity, abort cleanup, exact-handle rollback, and deferred recovery ownership.
  • 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: docs-updated
  • Evidence: The reviewed 23-file, +4,272/-0 slice remains byte-identical after the append-only current-main refresh to 0de2789608a86e580d787991e81c03c5f0b14dbf through e97ecce48c7fcc1dfb398e1cfae8c81a859b7dcd; stable patch ID remains dd1c4a899fd9a62954a00d4e2e61da445a306e03. The only documentation path is src/lib/onboard/managed-workload/rebuild/README.md. It accurately states that the transaction is dormant, has no CLI command or production-action importer, and does not activate buildless rebuilds. It assigns ambiguous publication and pending retirement to durable recovery, links recovery and snapshot/backup ownership to the live accepted epic [Epic] Support native Podman with buildless managed onboarding #7744, and requires normalized backup manifests, restore validation, durable reconciliation, and protected qualification for OpenClaw, Hermes, and LangChain Deep Agents Code before activation. Production-import and command/action diff scans found no activation caller. Markdownlint passed with zero issues on the exact refreshed head. The append-only parent refresh to 362a70cda preserves the exact reviewed slice diff and changes no reviewed documentation.
  • Agent: Codex Desktop

DGX Station Hardware Evidence

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

Verification

  • Exact locally validated head/base: e97ecce48c7fcc1dfb398e1cfae8c81a859b7dcd / 0de2789608a86e580d787991e81c03c5f0b14dbf
  • Review budget: 23 files, +4,272/-0.
  • Stable exact-slice patch ID: dd1c4a899fd9a62954a00d4e2e61da445a306e03.
  • The six implementation/review commits and both maintainer refresh commits are SSH-signed and contain DCO trailers; GitHub-generated conflict-resolution merge commits preserve append-only branch history.
  • npm run validate:pr passed on the exact clean head with Node 22.16.0.
  • 132 focused rebuild transaction, workload authority, registry CAS, and source-boundary tests passed again on the exact refreshed head; CLI typecheck and repository checks also passed; changed test files add zero if statements.
  • npm run build:cli, CLI typecheck through validate:pr, exact-base pre-commit, commitlint, and pre-push gates passed.
  • Failure tests prove prepare/create ambiguity aborts exact transaction resources, staged failures roll back only exact staging authority, and indeterminate CAS never rolls back.
  • Agent-binding tests reject cross-agent image/profile drift for all shipped managed-image agents.
  • No snapshot manifest dependency, production rebuild callsite, runtime selection change, or public activation exists in this slice.
  • Applicable broad gate passed — exact-head required CI, advisors, CodeRabbit, multiarch, and protected E2E are the broad remote gates.

Stack

Signed-off-by: Aaron Erickson aerickson@nvidia.com

Summary by CodeRabbit

  • New Features

    • Added managed workload rebuild workflows with staged replacement, validation, rollback, recovery, and atomic commit handling.
    • Added authority validation for managed workloads, including receipt, image, platform, and startup configuration checks.
    • Added safe cloning and deep-freezing for supported immutable data.
    • Added safeguards against stale, conflicting, or incomplete workload state during rebuilds.
  • Documentation

    • Documented rebuild recovery behavior and activation requirements.
  • Tests

    • Added comprehensive coverage for rebuild transactions, authority validation, rollback, persistence reconciliation, and immutable data handling.

ericksoa added 30 commits July 30, 2026 14:50
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the exact reviewed tree while moving the stacked base to merged PR3.3.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the exact reviewed tree while moving the stacked base to restacked PR3.4a.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Preserve the exact reviewed tree while moving the stacked base to restacked PR3.4b.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Carry the reviewed PR3.4b slice unchanged onto the CodeRabbit feedback fix for PR3.4a.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Carry the reviewed PR3.5 slice unchanged onto the CodeRabbit feedback restack through PR3.4b.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Carry the reviewed PR3.4b slice unchanged onto the serialized PR3.4a transaction contract.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Carry the reviewed PR3.5 slice unchanged onto the serialized PR3.4a transaction contract.

The review patch remains unchanged through PR3.4b.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Restack PR3.4b without changing its review patch.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Restack PR3.5 without changing its review patch.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa ericksoa added the platform: container Affects Docker, containerd, Podman, or images label Jul 31, 2026
@github-code-quality

github-code-quality Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Overview

Languages: TypeScript

TypeScript / code-coverage/plugin

The overall coverage in commit 362a70c in the feat/managed-workloa... branch remains at 96%, unchanged from commit b5aaa27 in the main branch.

TypeScript / code-coverage/cli

The overall coverage in commit 362a70c in the feat/managed-workloa... branch remains at 81%, unchanged from commit b5aaa27 in the main branch.

Show a code coverage summary of the most impacted files.
File main b5aaa27 feat/managed-workloa... 362a70c +/-
src/lib/onboard...box-prebuild.ts 92% 74% -18%
src/lib/onboard/docker-cdi.ts 70% 80% +10%
src/lib/onboard...load/rebuild.ts 0% 84% +84%
src/lib/onboard...build/commit.ts 0% 85% +85%
src/lib/onboard...rebuild/plan.ts 0% 86% +86%
src/lib/state/r...ld-authority.ts 0% 88% +88%
src/lib/onboard...ad/authority.ts 0% 88% +88%
src/lib/onboard...d/validation.ts 0% 91% +91%
src/lib/core/immutable.ts 0% 97% +97%
src/lib/onboard.../transaction.ts 0% 98% +98%

Updated August 01, 2026 12:15 UTC

Represent agent fixtures as data and route injected failures through one named helper.

This preserves every rebuild scenario without adding conditional statements to test files.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@github-actions

github-actions Bot commented Jul 31, 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 · 0 warnings · 0 suggestions
  • Model comparison: normalized findings match; normalized E2E selections differ; severity counts match.
1 additional E2E selection from the second opinion

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

  • rebuild-hermes-stale-base: The completed second-opinion lane identified E2E coverage that the primary lane omitted.

Second-opinion E2E selections are advisory. They do not change the primary assessment or E2E / PR Gate.

E2E guidance

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

Recommended E2E: onboard-repair, onboard-resume, rebuild-openclaw, state-backup-restore, cloud-onboard

1 optional E2E recommendation
  • rebuild-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: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

Copy link
Copy Markdown
Contributor Author

PRA-1 is addressed in verified commit add39657c6: the transaction suite now injects invalid binding, NUL/oversized handles, changed old/staging handles, and altered readiness/restore receipts across prepare, create, readiness, restore, and provider-rebind. Each case proves no later phase runs and asserts either exact transaction abort or rollback of runtime-new-staged-exact. The exact head passes 117 focused tests, CLI typecheck, and full local validate:pr; remote exact-head gates are now rerunning.

@ericksoa

Copy link
Copy Markdown
Contributor Author

Maintainer disposition for the current exact-head PRA-1: the dormant boundary is intentional and required by the incremental contract in #7744. This slice makes the rebuild authority, rollback, recovery-task handoff, and provider-neutral transaction internally complete while keeping it inert. Production caller ownership, durable reconciliation, and activation are assigned to the downstream slices; wiring this into a supported action here would activate an incomplete all-agent path before recovery and protected qualification, violating the stack gate. We are therefore retaining the foundation without activating it in this PR. The warning is acknowledged and does not require a code change.

@ericksoa

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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

🧹 Nitpick comments (13)
src/lib/state/registry-rebuild-authority.test.ts (2)

20-36: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Build the reference from MANAGED_IMAGE_REPOSITORIES.

requireReceiptAgent derives the expected prefix from MANAGED_IMAGE_REPOSITORIES[agent]. This fixture hard-codes the same string, so a change to the production constant makes every case in this suite fail for an unrelated reason. The companion suite src/lib/onboard/sandbox-workload-authority.test.ts already imports the constant.

♻️ Proposed fix for the fixture reference
+import { MANAGED_IMAGE_REPOSITORIES } from "../onboard/managed-image/contract";
 import { encodeManagedStartupProfile } from "../onboard/managed-startup/profile";
-    reference: `ghcr.io/nvidia/nemoclaw/openclaw-sandbox@sha256:${digest.repeat(64)}`,
+    reference: `${MANAGED_IMAGE_REPOSITORIES.openclaw}`@sha256`:${digest.repeat(64)}`,
🤖 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/state/registry-rebuild-authority.test.ts` around lines 20 - 36,
Update the receipt fixture’s reference construction in receipt to derive its
repository prefix from MANAGED_IMAGE_REPOSITORIES, matching requireReceiptAgent
and the companion test suite, instead of hard-coding the image repository
string.

78-225: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for the locked publication and reconciliation paths.

The suite covers captureSandboxRebuildAuthority, sandboxRebuildAuthorityMatchesEntry, and the pure swapSandboxRebuildAuthorityInRegistry. Two exported functions that carry the durable-write risk have no case:

  • compareAndSwapSandboxRebuildAuthority, including the branch where save fails and reconciliation returns "committed".
  • sandboxRebuildReplacementMatchesEntry, including the documented rule that mutable non-authority fields are ignored.

Do you want me to generate these cases with load and save stubbed at the persistence boundary?

🤖 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/state/registry-rebuild-authority.test.ts` around lines 78 - 225,
Extend the sandbox rebuild authority tests to cover
compareAndSwapSandboxRebuildAuthority with load/save stubs, including save
failure followed by reconciliation returning "committed". Add coverage for
sandboxRebuildReplacementMatchesEntry proving replacements match when only
mutable non-authority fields differ, while authority fields still require exact
matches. Keep the tests focused on the persistence boundary and documented
matching behavior.
src/lib/state/registry/rebuild-authority.ts (1)

283-300: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Limit reconciliation to ambiguous persistence failures.

The catch block reconciles for every error. validateReplacement throws SandboxRebuildAuthorityError before any write, so a rejected replacement still triggers a registry read. That read also runs outside withLock, so it can observe the registry while another writer saves it.

Validate the replacement before entering the try block, and reconcile only for a failure that can leave publication ambiguous.

♻️ Proposed scoping of the reconciliation branch
 export function compareAndSwapSandboxRebuildAuthority(
   expected: SandboxRebuildAuthority,
   replacement: SandboxEntry,
 ): SandboxRebuildAuthoritySwapResult {
+  validateReplacement(expected, replacement);
   try {
     return withLock(() => {
       const swapped = swapSandboxRebuildAuthorityInRegistry(load(), expected, replacement);
       if (swapped.result.status === "committed") save(swapped.registry);
       return swapped.result;
     });
   } catch (error) {
+    if (error instanceof SandboxRebuildAuthorityError) throw error;
     try {
🤖 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/state/registry/rebuild-authority.ts` around lines 283 - 300, Update
the surrounding registry replacement function to call validateReplacement before
entering the try/withLock block, so rejected replacements do not trigger
reconciliation. Narrow the catch reconciliation path to only persistence
failures that may leave publication ambiguous, preserving direct propagation for
validation and other pre-write errors; keep reconciliation under the existing
lock to avoid observing concurrent saves.
src/lib/onboard/workload/rebuild.ts (1)

435-446: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Delete the unused exported aliases.

ManagedWorkloadRebuildEntry and ManagedWorkloadRebuildReceipt have no repository consumers. If a rebuild receipt type is required, use the managed-only ManagedWorkloadReceipt alias instead of the full SandboxWorkloadReceipt union.

🤖 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/workload/rebuild.ts` around lines 435 - 446, Remove the
unused exported aliases ManagedWorkloadRebuildEntry and
ManagedWorkloadRebuildReceipt from the rebuild module. Do not replace them with
another alias; if a rebuild receipt type is needed elsewhere in the module, use
the existing managed-only ManagedWorkloadReceipt type instead of
SandboxWorkloadReceipt.

Source: Coding guidelines

src/lib/core/immutable.ts (1)

4-23: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Define cloneAndDeepFreeze’s supported input shape.

Object.freeze does not prevent Map, Set, or Date mutations. It throws a TypeError for non-empty typed arrays, including Buffer. Add a plain-data type or JSDoc contract. Remove the unreachable function branch if plain data is the intended scope.

🤖 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/core/immutable.ts` around lines 4 - 23, Define and enforce a
plain-data input contract for cloneAndDeepFreeze, documenting that Map, Set,
Date, typed arrays, Buffer, and functions are unsupported. Narrow the
generic/type signature and update deepFreezeOwnedValue accordingly, removing its
unreachable function handling while preserving recursive freezing for supported
plain objects and arrays.
src/lib/onboard/managed-workload/rebuild/readiness.ts (1)

18-26: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider documenting the readiness timeout obligation.

operations.waitUntilReady has no bound in this layer. If a provider implementation never settles, the transaction stalls with a staged runtime allocated and no rollback. The contract for prepare, abortPreparation, and rollback states exactness and idempotency obligations, but waitUntilReady in src/lib/onboard/managed-workload/rebuild/contract.ts (Lines 108-111) states none.

Add a doc comment on waitUntilReady that names the provider as the owner of the readiness deadline, and require it to return { state: "not-ready" } on timeout rather than hang. That keeps the central orchestration provider-neutral and keeps rollback reachable.

🤖 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/managed-workload/rebuild/readiness.ts` around lines 18 - 26,
Update the waitUntilReady contract in the rebuild contract definition to
document that the provider owns and enforces the readiness deadline, and must
return { state: "not-ready" } when the deadline expires rather than leaving the
promise pending. Keep the existing provider-neutral orchestration in the
readiness flow unchanged.
src/lib/onboard/managed-workload-rebuild-transaction.test.ts (4)

857-860: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Also assert that a sequential rollback retry stays coalesced.

Promise.all starts the three calls together, so this proves that concurrent calls collapse into one provider operation. The contract in contract.ts states that rollback must be safe to retry. A retry is normally sequential: the caller awaits, then calls again. Add one awaited call after the concurrent batch, so the memoized-result behavior is pinned for that case too.

💚 Proposed change
     await Promise.all([rollback.run(), rollback.run(), rollback.run()]);
+    await rollback.run();
 
     expect(providerOperations.rollback).toHaveBeenCalledOnce();
     expect(events).toEqual(["rollback:runtime-new-staged-exact"]);
🤖 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/managed-workload-rebuild-transaction.test.ts` around lines
857 - 860, Extend the rollback coalescing test around the concurrent Promise.all
call by awaiting one additional rollback.run() afterward. Keep the existing
providerOperations.rollback and events assertions, ensuring the sequential retry
reuses the memoized result without triggering another provider operation or
event.

395-406: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Loosen the read-count coupling in the injected registry read.

registryReadCount === 2 on Line 398 encodes the exact number of getSandbox calls that runManagedWorkloadRebuildTransaction makes before staging. The transaction currently reads twice, once before preparation and once after. If a later slice adds another revalidation read, this injection lands on a different call site. The test would keep passing while it no longer exercises the post-preparation read failure.

Key the injection on the transaction phase instead of the call count. For example, set a flag when operations.prepare resolves, then fail the next read while that flag is set.

🤖 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/managed-workload-rebuild-transaction.test.ts` around lines
395 - 406, The injected registry-read failure in getSandbox is coupled to
registryReadCount === 2 and may target the wrong read after transaction changes.
Track the transaction phase by setting a flag when operations.prepare resolves,
then fail the next getSandbox call while that flag is set; preserve the separate
ambiguous-persistence readback injection.

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

Add a case that injects an abortPreparation failure.

FailurePhase declares "abort-preparation" on Line 255, and operationsHarness wires it on Line 310. No test in this file sets failAt to "abort-preparation". The scaffolding is therefore inert.

That gap leaves the cleanup-failure path in transaction.ts untested. failAfterCleanup catches a cleanup rejection and attaches it as rollbackError on the thrown ManagedWorkloadRebuildTransactionError. No assertion in this suite proves that the original phase and message survive, or that rollbackError carries the cleanup error. The PR objectives describe strengthened fail-closed behavior, so this path deserves coverage.

💚 Proposed test case
it("preserves the original failure when abort of preparation also fails", async () => {
  const events: string[] = [];
  const operations = operationsHarness("mxc", events, "abort-preparation");
  const prepare = operations.prepare;
  operations.prepare = vi.fn(async (plan) => {
    await prepare(plan);
    throw new Error("prepare injected failure");
  });
  const oldEntry = previousEntry("openclaw", "mxc");

  await expect(
    runManagedWorkloadRebuildTransaction(
      {
        previousEntry: oldEntry,
        provider: bundle("mxc"),
        handoff: handoff("openclaw", "mxc"),
        operations,
        transactionId: "transaction-1",
      },
      { getSandbox: () => structuredClone(oldEntry) },
    ),
  ).rejects.toMatchObject({
    phase: "prepare",
    message: expect.stringContaining("prepare injected failure"),
    rollbackError: expect.any(Error),
  });
  expect(events).toEqual(["prepare", "abort-preparation:transaction-1"]);
});

Also applies to: 308-311

🤖 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/managed-workload-rebuild-transaction.test.ts` at line 255,
Add a test covering the abort-preparation failure path in the transaction test
suite. Use operationsHarness with failAt set to "abort-preparation", inject a
prepare failure, and assert the rejected ManagedWorkloadRebuildTransactionError
preserves phase "prepare", the original message, and an Error-valued
rollbackError. Also verify the events contain the prepare and abort-preparation
entries in order.

892-892: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Assert the phase for the cross-platform rejection.

This test uses rejects.toThrow(). The neighbouring pre-mutation tests on Lines 921 and 946 assert { phase: "prepare" }. A bare toThrow() passes for any error, including one thrown by the fixture builders instead of by the plan validation.

💚 Proposed change
-    ).rejects.toThrow();
+    ).rejects.toMatchObject({ phase: "prepare" });
🤖 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/managed-workload-rebuild-transaction.test.ts` at line 892,
Update the cross-platform rejection assertion in the relevant test to verify the
error has phase "prepare", matching the neighbouring pre-mutation tests. Keep
the rejection assertion focused on plan validation so fixture-builder errors
cannot satisfy it.
src/lib/onboard/managed-workload-rebuild-source-shape.test.ts (2)

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

Remove the whitespace-exact doc-comment assertion.

This assertion depends on the exact line wrapping of a JSDoc comment in contract.ts, including the \n * continuation. A formatter width change or a wording tweak breaks the test, and neither changes behavior. Lines 53-56 already assert the identifiers that carry the contract: previousRuntimeHandle, stagingHandle, retirePrevious(, and rollback(.

♻️ Proposed change
     expect(contract).toContain("retirePrevious(");
     expect(contract).toContain("rollback(");
-    expect(contract).toContain("A sandbox name is\n   * intentionally insufficient authority");
   });

If the intent is to keep the documented rule under test, match the wording without the comment layout:

+    expect(contract.replace(/\s+/gu, " ")).toContain(
+      "A sandbox name is intentionally insufficient authority",
+    );

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/onboard/managed-workload-rebuild-source-shape.test.ts` at line 57,
Remove the whitespace-sensitive contract assertion in the test around the JSDoc
text. Keep the existing identifier assertions for previousRuntimeHandle,
stagingHandle, retirePrevious(, and rollback(, and do not replace the removed
source-layout check unless a wording-only assertion is explicitly required.

Source: Path instructions


10-27: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Enumerate the directory so new modules cannot escape the boundary checks.

CENTRAL_REBUILD_MODULES is a hardcoded list. A later slice that adds a module to managed-workload/rebuild/ will not be checked for provider-specific imports or name-only deletion, and no test will fail. Read the directory instead, so the guarantee covers every module in the boundary.

♻️ Proposed change
 const ROOT = path.resolve(import.meta.dirname, "managed-workload/rebuild");
-const CENTRAL_REBUILD_MODULES = [
-  "commit.ts",
-  "contract.ts",
-  "create.ts",
-  "plan.ts",
-  "prepare.ts",
-  "provider-rebind.ts",
-  "readiness.ts",
-  "recovery.ts",
-  "restore.ts",
-  "rollback.ts",
-  "transaction.ts",
-  "validation.ts",
-] as const;
+const CENTRAL_REBUILD_MODULES = fs
+  .readdirSync(ROOT)
+  .filter((entry) => entry.endsWith(".ts") && !entry.endsWith(".test.ts"))
+  .sort();
 
-function source(file: (typeof CENTRAL_REBUILD_MODULES)[number]): string {
+function source(file: string): string {
   return fs.readFileSync(path.join(ROOT, file), "utf8");
 }

Add an assertion that the directory is not empty, so a wrong ROOT cannot make every it.each case vanish:

expect(CENTRAL_REBUILD_MODULES.length).toBeGreaterThan(0);
🤖 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/managed-workload-rebuild-source-shape.test.ts` around lines
10 - 27, Replace the hardcoded CENTRAL_REBUILD_MODULES list with a directory
enumeration of ROOT, including every rebuild module and preserving the existing
filename-based source checks. Keep source aligned with the discovered module
names, and assert CENTRAL_REBUILD_MODULES is non-empty so an incorrect ROOT
cannot silently skip all parameterized tests.
src/lib/onboard/managed-workload/rebuild/index.ts (1)

4-6: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused rebuild barrel.

No source or test imports src/lib/onboard/managed-workload/rebuild/index.ts. The source-shape test does not protect this barrel, which exports only 3 of the 12 rebuild modules. Remove it until a consumer requires the barrel.

🤖 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/managed-workload/rebuild/index.ts` around lines 4 - 6, Remove
the unused rebuild barrel file that contains the exports from contract,
recovery, and transaction. Do not replace or expand it; retain the individual
rebuild modules and their direct imports unchanged.

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.

Inline comments:
In `@src/lib/onboard/managed-workload-rebuild-transaction.test.ts`:
- Line 714: Rename the test case around sandboxRebuildAuthorityMatchesEntry to
state that preparation aborts when authority-relevant registry metadata,
specifically the model field, drifts. Keep the assertions and test behavior
unchanged.

In `@src/lib/onboard/managed-workload/rebuild/README.md`:
- Around line 24-28: Update the deferred-work references in the README,
including the recovery owner on lines 13–16 and the snapshot/backup slice, to
use resolvable GitHub issue or pull request links instead of stack-position
labels. Explicitly state that this change migrates only the documented slice,
link the durable recovery work, and describe the observable conditions—every
relevant caller emits the shared managed manifest accepted by the restore
gate—required for the rebuild transaction to leave its dormant state.
- Line 1: Add the repository’s standard SPDX license header to the top of the
Markdown file as an HTML comment, before the existing “Managed workload rebuild
boundary” heading, using the project’s established license and copyright values.

In `@src/lib/onboard/managed-workload/rebuild/transaction.ts`:
- Around line 112-118: In
src/lib/onboard/managed-workload/rebuild/transaction.ts lines 112-118, validate
input.operations.providerId against plan.providerId immediately after
createManagedWorkloadRebuildPlan, throwing
ManagedWorkloadRebuildTransactionError with phase "prepare" on mismatch; remove
the now-unreachable rethrow from the prepare catch. In
src/lib/onboard/managed-workload-rebuild-transaction.test.ts lines 987-1004,
assert that operations.prepare and operations.abortPreparation are not called
for the mismatched adapter case.

In `@src/lib/onboard/sandbox-workload-authority.test.ts`:
- Around line 65-73: Update the test around readManagedWorkloadAuthority to
store the result of managedEntry(agent, platform) in a single entry variable and
pass that same instance to the reader. Compare authority?.receipt against
entry.workload by reference so the assertion verifies cloning rather than
comparing two separately constructed objects.
- Around line 121-128: Retitle the test case around readManagedWorkloadAuthority
to describe the validation it actually exercises: rejection of a mismatch
between the image reference agent and the startup profile agent. Keep the test
setup and assertions unchanged.

In `@src/lib/onboard/sandbox-workload-rebuild.test.ts`:
- Around line 508-510: Update the assertions in the staged replacement-profile
test to decode staged.replacementProfile.encodedProfile using the existing
decoding helper used by nearby cases, then assert the decoded profile does not
contain the persisted credential. Remove the encoded transport substring check
and retain the public decoded-profile outcome assertion.

---

Nitpick comments:
In `@src/lib/core/immutable.ts`:
- Around line 4-23: Define and enforce a plain-data input contract for
cloneAndDeepFreeze, documenting that Map, Set, Date, typed arrays, Buffer, and
functions are unsupported. Narrow the generic/type signature and update
deepFreezeOwnedValue accordingly, removing its unreachable function handling
while preserving recursive freezing for supported plain objects and arrays.

In `@src/lib/onboard/managed-workload-rebuild-source-shape.test.ts`:
- Line 57: Remove the whitespace-sensitive contract assertion in the test around
the JSDoc text. Keep the existing identifier assertions for
previousRuntimeHandle, stagingHandle, retirePrevious(, and rollback(, and do not
replace the removed source-layout check unless a wording-only assertion is
explicitly required.
- Around line 10-27: Replace the hardcoded CENTRAL_REBUILD_MODULES list with a
directory enumeration of ROOT, including every rebuild module and preserving the
existing filename-based source checks. Keep source aligned with the discovered
module names, and assert CENTRAL_REBUILD_MODULES is non-empty so an incorrect
ROOT cannot silently skip all parameterized tests.

In `@src/lib/onboard/managed-workload-rebuild-transaction.test.ts`:
- Around line 857-860: Extend the rollback coalescing test around the concurrent
Promise.all call by awaiting one additional rollback.run() afterward. Keep the
existing providerOperations.rollback and events assertions, ensuring the
sequential retry reuses the memoized result without triggering another provider
operation or event.
- Around line 395-406: The injected registry-read failure in getSandbox is
coupled to registryReadCount === 2 and may target the wrong read after
transaction changes. Track the transaction phase by setting a flag when
operations.prepare resolves, then fail the next getSandbox call while that flag
is set; preserve the separate ambiguous-persistence readback injection.
- Line 255: Add a test covering the abort-preparation failure path in the
transaction test suite. Use operationsHarness with failAt set to
"abort-preparation", inject a prepare failure, and assert the rejected
ManagedWorkloadRebuildTransactionError preserves phase "prepare", the original
message, and an Error-valued rollbackError. Also verify the events contain the
prepare and abort-preparation entries in order.
- Line 892: Update the cross-platform rejection assertion in the relevant test
to verify the error has phase "prepare", matching the neighbouring pre-mutation
tests. Keep the rejection assertion focused on plan validation so
fixture-builder errors cannot satisfy it.

In `@src/lib/onboard/managed-workload/rebuild/index.ts`:
- Around line 4-6: Remove the unused rebuild barrel file that contains the
exports from contract, recovery, and transaction. Do not replace or expand it;
retain the individual rebuild modules and their direct imports unchanged.

In `@src/lib/onboard/managed-workload/rebuild/readiness.ts`:
- Around line 18-26: Update the waitUntilReady contract in the rebuild contract
definition to document that the provider owns and enforces the readiness
deadline, and must return { state: "not-ready" } when the deadline expires
rather than leaving the promise pending. Keep the existing provider-neutral
orchestration in the readiness flow unchanged.

In `@src/lib/onboard/workload/rebuild.ts`:
- Around line 435-446: Remove the unused exported aliases
ManagedWorkloadRebuildEntry and ManagedWorkloadRebuildReceipt from the rebuild
module. Do not replace them with another alias; if a rebuild receipt type is
needed elsewhere in the module, use the existing managed-only
ManagedWorkloadReceipt type instead of SandboxWorkloadReceipt.

In `@src/lib/state/registry-rebuild-authority.test.ts`:
- Around line 20-36: Update the receipt fixture’s reference construction in
receipt to derive its repository prefix from MANAGED_IMAGE_REPOSITORIES,
matching requireReceiptAgent and the companion test suite, instead of
hard-coding the image repository string.
- Around line 78-225: Extend the sandbox rebuild authority tests to cover
compareAndSwapSandboxRebuildAuthority with load/save stubs, including save
failure followed by reconciliation returning "committed". Add coverage for
sandboxRebuildReplacementMatchesEntry proving replacements match when only
mutable non-authority fields differ, while authority fields still require exact
matches. Keep the tests focused on the persistence boundary and documented
matching behavior.

In `@src/lib/state/registry/rebuild-authority.ts`:
- Around line 283-300: Update the surrounding registry replacement function to
call validateReplacement before entering the try/withLock block, so rejected
replacements do not trigger reconciliation. Narrow the catch reconciliation path
to only persistence failures that may leave publication ambiguous, preserving
direct propagation for validation and other pre-write errors; keep
reconciliation under the existing lock to avoid observing concurrent saves.
🪄 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: 414dc072-996e-4e6d-b0e0-14970039e500

📥 Commits

Reviewing files that changed from the base of the PR and between 75730cf and add3965.

📒 Files selected for processing (23)
  • src/lib/core/immutable.ts
  • src/lib/onboard/managed-workload-rebuild-source-shape.test.ts
  • src/lib/onboard/managed-workload-rebuild-transaction.test.ts
  • src/lib/onboard/managed-workload/rebuild/README.md
  • src/lib/onboard/managed-workload/rebuild/commit.ts
  • src/lib/onboard/managed-workload/rebuild/contract.ts
  • src/lib/onboard/managed-workload/rebuild/create.ts
  • src/lib/onboard/managed-workload/rebuild/index.ts
  • src/lib/onboard/managed-workload/rebuild/plan.ts
  • src/lib/onboard/managed-workload/rebuild/prepare.ts
  • src/lib/onboard/managed-workload/rebuild/provider-rebind.ts
  • src/lib/onboard/managed-workload/rebuild/readiness.ts
  • src/lib/onboard/managed-workload/rebuild/recovery.ts
  • src/lib/onboard/managed-workload/rebuild/restore.ts
  • src/lib/onboard/managed-workload/rebuild/rollback.ts
  • src/lib/onboard/managed-workload/rebuild/transaction.ts
  • src/lib/onboard/managed-workload/rebuild/validation.ts
  • src/lib/onboard/sandbox-workload-authority.test.ts
  • src/lib/onboard/sandbox-workload-rebuild.test.ts
  • src/lib/onboard/workload/authority.ts
  • src/lib/onboard/workload/rebuild.ts
  • src/lib/state/registry-rebuild-authority.test.ts
  • src/lib/state/registry/rebuild-authority.ts

Comment thread src/lib/onboard/managed-workload-rebuild-transaction.test.ts Outdated
Comment thread src/lib/onboard/managed-workload/rebuild/README.md
Comment thread src/lib/onboard/managed-workload/rebuild/README.md Outdated
Comment thread src/lib/onboard/managed-workload/rebuild/transaction.ts
Comment thread src/lib/onboard/sandbox-workload-authority.test.ts Outdated
Comment thread src/lib/onboard/sandbox-workload-authority.test.ts Outdated
Comment thread src/lib/onboard/sandbox-workload-rebuild.test.ts
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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/state/registry-rebuild-authority.test.ts (1)

33-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider extracting the duplicated receipt() fixture.

This receipt() function is identical to the one in src/lib/onboard/workload/rebuild.ts, src/lib/onboard/sandbox-workload-authority.test.ts, and src/lib/onboard/managed-workload-rebuild-transaction.test.ts. Four copies of the same managed-image receipt fixture increase drift risk: a future schema change to SandboxWorkloadReceipt requires updating all four files in sync.

Move this helper to a shared test-fixture module under src/lib/ and import it from each test file.

🤖 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/state/registry-rebuild-authority.test.ts` around lines 33 - 49,
Extract the duplicated managed-image receipt fixture into a shared test-fixture
module under src/lib/, preserving the existing receipt behavior and exported
API. Remove the local receipt() definitions from
registry-rebuild-authority.test.ts, rebuild.ts,
sandbox-workload-authority.test.ts, and
managed-workload-rebuild-transaction.test.ts, then import and reuse the shared
helper in each file.
src/lib/core/immutable.test.ts (1)

27-49: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for circular references.

assertPlainData and deepFreezeOwnedValue both use a WeakSet to detect cycles, and structuredClone supports circular graphs. No test exercises this path. Add a case with a self-referencing plain object to confirm cloneAndDeepFreeze does not throw and does not overflow the stack.

✅ Suggested additional test
+  it("supports circular references without throwing", () => {
+    const source: { self?: unknown } = {};
+    source.self = source;
+
+    const result = cloneAndDeepFreeze(source) as { self: unknown };
+
+    expect(result.self).toBe(result);
+    expect(Object.isFrozen(result)).toBe(true);
+  });
+
🤖 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/core/immutable.test.ts` around lines 27 - 49, Add a test near the
existing cloneAndDeepFreeze rejection cases using a plain object whose property
references itself, then assert cloneAndDeepFreeze accepts it without throwing
and preserves the circular relationship in the returned clone. Anchor the test
to cloneAndDeepFreeze and verify execution completes without stack overflow.
🤖 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/core/immutable.test.ts`:
- Around line 27-49: Add a test near the existing cloneAndDeepFreeze rejection
cases using a plain object whose property references itself, then assert
cloneAndDeepFreeze accepts it without throwing and preserves the circular
relationship in the returned clone. Anchor the test to cloneAndDeepFreeze and
verify execution completes without stack overflow.

In `@src/lib/state/registry-rebuild-authority.test.ts`:
- Around line 33-49: Extract the duplicated managed-image receipt fixture into a
shared test-fixture module under src/lib/, preserving the existing receipt
behavior and exported API. Remove the local receipt() definitions from
registry-rebuild-authority.test.ts, rebuild.ts,
sandbox-workload-authority.test.ts, and
managed-workload-rebuild-transaction.test.ts, then import and reuse the shared
helper in each file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 6d786b82-64f8-4f1c-a2a6-f139f634955f

📥 Commits

Reviewing files that changed from the base of the PR and between add3965 and 9bbf75d.

📒 Files selected for processing (12)
  • src/lib/core/immutable.test.ts
  • src/lib/core/immutable.ts
  • src/lib/onboard/managed-workload-rebuild-source-shape.test.ts
  • src/lib/onboard/managed-workload-rebuild-transaction.test.ts
  • src/lib/onboard/managed-workload/rebuild/README.md
  • src/lib/onboard/managed-workload/rebuild/contract.ts
  • src/lib/onboard/managed-workload/rebuild/transaction.ts
  • src/lib/onboard/sandbox-workload-authority.test.ts
  • src/lib/onboard/sandbox-workload-rebuild.test.ts
  • src/lib/onboard/workload/rebuild.ts
  • src/lib/state/registry-rebuild-authority.test.ts
  • src/lib/state/registry/rebuild-authority.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/lib/onboard/managed-workload/rebuild/README.md
  • src/lib/onboard/sandbox-workload-authority.test.ts
  • src/lib/onboard/sandbox-workload-rebuild.test.ts
  • src/lib/state/registry/rebuild-authority.ts
  • src/lib/onboard/managed-workload/rebuild/transaction.ts

Base automatically changed from feat/runtime-provider-lifecycle-parity to feat/buildless-managed-contract-hardening July 31, 2026 20:05
Base automatically changed from feat/buildless-managed-contract-hardening to main August 1, 2026 00:49
@copy-pr-bot

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

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
@ericksoa
ericksoa merged commit 5cd29cc into main Aug 1, 2026
67 of 68 checks passed
@ericksoa
ericksoa deleted the feat/managed-workload-rebuild-parity branch August 1, 2026 15:22
ericksoa added a commit that referenced this pull request Aug 2, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Adds provider-neutral managed snapshot, backup, and restore authority
for the incremental buildless stack. A normalized immutable runtime
snapshot is captured before backup, restored only through the owning
provider, and rebound to durable registry state only after exact live
identity and managed-profile proof agree.

This slice preserves current Docker behavior and supplies its provider
surface, but it does not register Podman, activate buildless onboarding,
or advertise partial runtime support. The contract applies uniformly to
OpenClaw, Hermes, and LangChain Deep Agents Code and remains pluggable
for an MXC-style provider.

## Related Issue

Part of #7744

## Changes

- Define a versioned provider-neutral runtime snapshot contract covering
exact provider/runtime identity, lifecycle state, image identity,
acceleration selectors, and opaque provider authority.
- Add provider-owned backup and restore preflight/receipt surfaces with
strict identity, profile, and operation binding.
- Capture Docker runtime identity and GPU attachment evidence inside the
Docker provider rather than central snapshot orchestration.
- Bind managed backup manifests to immutable runtime snapshots and fail
closed when managed authority is absent, stale, ambiguous, or
provider-mismatched.
- Restore through the owning provider, verify the exact post-restore
runtime, and publish registry state only after provider acceptance and
managed-profile proof.
- Preserve stopped-sandbox, rebuild-restore, and existing snapshot
behavior while adding exact rollback and ordering tests.
- Document the internal lifecycle ownership boundary for all shipped
agents.
- Keep runtime selection opaque; no central Podman switch or production
Podman registration is introduced.
- Keep changed test bodies linear; the exact-head growth guard now
reports no added `if` statements.

## Type of Change

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

## Quality Gates

- [x] Tests added or updated for changed behavior
- [ ] Existing tests cover changed behavior — justification:
- [ ] Tests not applicable — justification:
- [x] Docs updated for user-facing behavior changes
- [ ] Docs not applicable — justification:
- [x] Sensitive paths changed (security, policy, credentials, preflight,
onboarding, inference, runner, sandbox, or messaging)
- [x] Sensitive-path review completed or maintainer-approved waiver
recorded — reviewer/approval link/justification: Exact-head audit covers
immutable provider/runtime authority, backup/restore ordering,
acceleration preservation, fail-closed validation, and post-restore
registry publication.
- [ ] 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: Reviewed `src/lib/onboard/lifecycle-contracts.md` at exact
head/base `6b2c4646d021e87da7d5fd5997138736f1052beb` /
`e97ecce48c7fcc1dfb398e1cfae8c81a859b7dcd`. It accurately documents
managed snapshot authority, provider-owned backup/restore behavior,
registry-binding order, and fail-closed restore semantics for OpenClaw,
Hermes, and DCode. This internal slice activates and advertises no
user-visible buildless or Podman support, so no public support guide
change belongs here. The exact-head follow-ups linearize tests and
harden snapshot hashing against path races without changing the
documented contract or activating support. The append-only parent
refresh through `33d1756d48500fe42552cd6fb41b2ad851e06ea4` preserves the
reviewed documentation and exact snapshot authority thesis while
rebasing the PR onto current `main`.
- Agent: Codex Desktop
<!-- docs-review-head-sha: 33d1756 -->
<!-- docs-review-agents-blob-sha:
36ce0c7 -->

## DGX Station Hardware Evidence

- [ ] Tested on DGX Station
- Tested commit:
- Station profile/scenario:
- Result:
- Supporting evidence:

## Verification

- Exact validated head/base: `33d1756d48500fe42552cd6fb41b2ad851e06ea4`
/ `d5b64a72a5fcb8299e8cec1c2f22746b5c0a7f32`.
- Review budget: 41 files, `+5,493/-82`; one cohesive
snapshot/backup/restore subsystem.
- Reviewed slice patch ID: `ff335c82cec863062374d1bd7c5759c03ca2d3c0`;
current-main PR-range patch ID:
`60555d96eaa7a26de6a0ae7cfcf9ca1cbb069ff5`.
- [x] All 91 PR-range commits are GitHub-verified; the three GitHub
Actions merge commits omit literal trailers, while the remaining commits
and PR body are signed off and the exact-head DCO check passes.
- [x] 381 affected snapshot, restore, provider-authority, registry, and
lifecycle tests passed across 19 files on the byte-identical
current-main refresh; the 62 tests changed by the linear-test follow-up
also pass.
- [x] The CodeQL filesystem-race finding is remediated with
no-follow/nonblocking descriptor pinning and post-read path/inode
verification; 78 affected restore and runtime-snapshot tests pass.
- [x] Architecture validation passed: 1,453 files, 4,297 edges, one
allowed cycle.
- [x] CLI typecheck, repository checks, exact-range merge
commit/commitlint, 381 focused tests, pre-push hooks, and `git diff
--check` passed on the refreshed head.
- [x] Current-main architecture baselines were preserved while snapshot
fan-out was ratcheted exactly `38 → 39`.
- [x] No Podman identity check or switch appears in central
orchestration.
- [x] No production Podman registration or public buildless activation
exists in this slice.
- [x] Applicable broad gate passed — exact-head required CI, both
advisor lanes, CodeRabbit, CodeQL, and protected E2E passed at
`33d1756d48500fe42552cd6fb41b2ad851e06ea4`.

## Risk Plan

- Primary risk: accepting stale or cross-provider restore authority and
publishing an incorrect runtime row.
- Containment: immutable preflight and completion receipts bind
provider, runtime, sandbox, image, profile, acceleration, and operation
identity; every mismatch fails closed before registry publication.
- Regression risk: current Docker snapshot and stopped-sandbox flows.
Existing and new focused tests cover backup, restore, rebuild
forwarding, stopped containers, GPU selectors, rollback, and publication
ordering.
- Rollback: this slice remains independently revertible and introduces
no production Podman selection or buildless activation.

## Stack

- Base: current `main` at `d5b64a72a5fcb8299e8cec1c2f22746b5c0a7f32`;
PR3.7 #8001 is merged.
- This slice: PR3.8 #8031, branch
`feat/managed-snapshot-parity-rebuild`, exact head
`33d1756d48500fe42552cd6fb41b2ad851e06ea4`.
- Next: PR3.9A #8032 narrows immutable clone handoff contracts and
remains inert on exact base `33d1756d48500fe42552cd6fb41b2ad851e06ea4`;
later transaction/rebind slices follow on exact predecessors.
- Buildless and Podman support remain disabled until the complete
all-agent, multiarch, GPU/local-inference, recovery, installer, and
protected-E2E activation gates in #7744 pass.

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>


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

* **New Features**
* Added managed snapshot backup and restore with workload, runtime,
provider, and content validation.
* Added Docker runtime snapshot support, including lifecycle and
GPU/NVIDIA metadata.
* Snapshot operations are serialized to prevent conflicts with
concurrent sandbox changes.
* **Bug Fixes**
* Added safeguards against stale, incompatible, corrupted, or
cross-sandbox restores.
  * Improved restore failure reporting and recovery guidance.
  * Preserved legacy and custom-image snapshot workflows.
* **Documentation**
* Added documentation describing managed snapshot and rebuild-restore
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Aaron Erickson <aerickson@nvidia.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
senthilr-nv added a commit that referenced this pull request Aug 4, 2026
<!-- markdownlint-disable MD041 -->
## Summary

Adds the canonical dated `v0.0.101` changelog entry that was missing
when the release tag was cut. This post-release recovery records the
shipped behavior on current `main` without changing or replacing the
existing tag.

## Changes

- Add `docs/changelog/2026-08-03.mdx` with the exact `## v0.0.101`
heading, release summary, detailed behavior changes, support boundaries,
and links to durable documentation.
- [#7317](#7317) ->
`docs/changelog/2026-08-03.mdx`: Records experimental OpenClaw Google
Chat support and its restricted credential and webhook boundary.
- [#7715](#7715) ->
`docs/changelog/2026-08-03.mdx`: Records strict onboarding recovery
state and authoritative resume identity.
- [#7749](#7749) ->
`docs/changelog/2026-08-03.mdx`: Records the provider-neutral policy
seam and unchanged runtime support boundary.
- [#7817](#7817) ->
`docs/changelog/2026-08-03.mdx`: Records preserved Hermes home-channel
assignments across rebuilds.
- [#7820](#7820) ->
`docs/changelog/2026-08-03.mdx`: Records the SSH-session status field
correction.
- [#7847](#7847) ->
`docs/changelog/2026-08-03.mdx`: Records fail-closed credential
filtering for migration and rebuild backups.
- [#7870](#7870) ->
`docs/changelog/2026-08-03.mdx`: Records sandbox-qualified in-sandbox
host command hints.
- [#7875](#7875) ->
`docs/changelog/2026-08-03.mdx`: Records Microsoft Teams stop and start
E2E coverage.
- [#7885](#7885) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed gateway
detection in status.
- [#7889](#7889) ->
`docs/changelog/2026-08-03.mdx`: Records policy-authenticated HTTPS Pin
Runtime route revocation.
- [#7891](#7891) ->
`docs/changelog/2026-08-03.mdx`: Records default fallback for negative
timeout and polling overrides.
- [#7993](#7993) ->
`docs/changelog/2026-08-03.mdx`: Records correct sibling detection
during uninstall.
- [#7995](#7995) ->
`docs/changelog/2026-08-03.mdx`: Records absent configuration-hash
handling before shields lock.
- [#8001](#8001) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant atomic managed
workload replacement foundation.
- [#8029](#8029) ->
`docs/changelog/2026-08-03.mdx`: Records repository terminology review
in PR Review Advisor.
- [#8031](#8031) ->
`docs/changelog/2026-08-03.mdx`: Records provider-neutral managed
snapshot authority.
- [#8032](#8032) ->
`docs/changelog/2026-08-03.mdx`: Records immutable managed clone handoff
contracts.
- [#8034](#8034) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant provider-owned
clone transaction surface.
- [#8035](#8035) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant Hermes managed
clone broker boundary.
- [#8036](#8036) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
managed bootstrap boundary.
- [#8037](#8037) ->
`docs/changelog/2026-08-03.mdx`: Records dormant Docker bootstrap
primitives and the unchanged provider support boundary.
- [#8070](#8070) ->
`docs/changelog/2026-08-03.mdx`: Records consolidated sandbox
resource-limit E2E coverage.
- [#8071](#8071) ->
`docs/changelog/2026-08-03.mdx`: Records escaped and bounded CLI
validation diagnostics.
- [#8081](#8081) ->
`docs/changelog/2026-08-03.mdx`: Records bounded linear snapshot Base64
validation.
- [#8085](#8085) ->
`docs/changelog/2026-08-03.mdx`: Records commit-bound workflow approval
for eligible same-repository maintainers.
- [#8088](#8088) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes managed-policy E2E
selection.
- [#8090](#8090) ->
`docs/changelog/2026-08-03.mdx`: Records pinned CI search-tool
provisioning.
- [#8106](#8106) ->
`docs/changelog/2026-08-03.mdx`: Records fallback from failed managed
OpenShell gateway startup.
- [#8107](#8107) ->
`docs/changelog/2026-08-03.mdx`: Records Hermes adapter lifecycle E2E
selection.
- [#8128](#8128) ->
`docs/changelog/2026-08-03.mdx`: Records the dormant transactional
Docker bootstrap adapter and rollback authority.
- [#8140](#8140) ->
`docs/changelog/2026-08-03.mdx`: Records Slack conflict scope across
independent OpenShell gateways.
- [#8147](#8147) ->
`docs/changelog/2026-08-03.mdx`: Records completion of durable v0.0.100
documentation audit follow-ups.

## 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: This documentation-only
recovery does not change executable behavior.
- [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: Independently reviewed `docs/changelog/2026-08-03.mdx` at
commit `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`. Its blob is
`82887920f9720eafd75db6b2271c35f7477edb9b`. The entry follows the
writing guide, controlled terminology, changelog structure, MDX SPDX
format, literal CLI-name rule, and root-absolute route requirements. It
accurately records the `v0.0.100...v0.0.101` release range, Announcement
#8162, accepted scope boundaries, and shipped security behavior. There
are no code samples. Focused changelog tests and the documentation build
pass for this commit.
- Agent: Codex Desktop independent documentation writer
<!-- docs-review-head-sha: 0bebe1f -->
<!-- docs-review-agents-blob-sha:
3dd7c24 -->

## Security Review

- Result: `PASS`
- Reviewed commit: `0bebe1f568e3dc85cf410aac1dfb8f8830070b85`
- Base commit: `643a4ab8b5f583d8555192a37927268b26022c51`
- Findings: None.
- Secrets and credentials: `PASS`. No credential values or secret files
are present.
- Input validation and data sanitization: `PASS`. No executable input
path changes.
- Authentication and authorization: `PASS`. No identity or permission
logic changes.
- Dependencies and third-party libraries: `PASS`. No dependency changes.
- Error handling and logging: `PASS`. No runtime path changes;
diagnostic-security claims are precise.
- Cryptography and data protection: `PASS`. No implementation changes.
- Configuration and security controls: `PASS`. No configuration,
container, port, or HTTP changes.
- Security testing: `PASS`. No coverage is removed; the entry records
shipped test and security behavior.
- System security: `PASS`. No runtime control changes; dormant and
non-activation boundaries are explicit.
- Agent: Codex Desktop independent security reviewer

## Verification

- [ ] PR description includes a `Signed-off-by:` line and every commit
appears as `Verified` in GitHub — verification is pending after commit
`0bebe1f568e3dc85cf410aac1dfb8f8830070b85` is pushed.
- [ ] 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 — commit hooks passed; pre-push is pending.
- [x] Targeted behavior tests pass for the current change set, or tests
are marked not applicable above — tests are not applicable to this
documentation-only recovery.
- [x] Applicable broad gate passed — not applicable to this
documentation-only recovery.
- [x] Quality Gates section completed with required justifications or
waivers
- [x] No secrets, API keys, credentials, or private keys are added by
this diff.
- [ ] `npm run docs` builds without warnings (doc changes only) — GitHub
documentation checks are pending.
- [x] Doc pages follow the [style
guide](https://github.com/NVIDIA/NemoClaw/blob/main/docs/CONTRIBUTING.md)
(doc changes only) — independent documentation review passed.
- [x] New doc pages include SPDX header and frontmatter (new pages only)
— the native changelog entry uses the required parser-safe MDX SPDX
comment and intentionally has no frontmatter.

GitHub CI is authoritative.
Focused changelog tests and `npm run docs` passed after the merge
refresh.

---
Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>


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

* **New Features**
  * Added experimental Google Chat support.
  * Improved runtime and session status visibility.
  * Added onboarding recovery and persistence safeguards.
  * Added snapshot validation and dormant managed-workload support.

* **Bug Fixes**
* Improved backup sanitization, route handling, and gateway reliability.

* **Documentation**
  * Added the v0.0.101 changelog and related updates.

* **Tests**
  * Expanded end-to-end coverage and strengthened trusted CI validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Apurv Kumaria <akumaria@nvidia.com>
Signed-off-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Carlos Villela <cvillela@nvidia.com>
Co-authored-by: Senthil Ravichandran <senthilr@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: onboarding Onboarding FSM, provider setup, sandbox launch, or first-run flow area: security Security controls, permissions, secrets, or hardening feature PR adds or expands user-visible functionality platform: container Affects Docker, containerd, Podman, or images

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant