Skip to content

fix(snapshot): make environment restore complete and atomic - #72

Merged
fuller-stack-dev merged 1 commit into
openclaw:mainfrom
fuller-stack-dev:fix/atomic-whole-root-snapshots
Aug 11, 2026
Merged

fix(snapshot): make environment restore complete and atomic#72
fuller-stack-dev merged 1 commit into
openclaw:mainfrom
fuller-stack-dev:fix/atomic-whole-root-snapshots

Conversation

@fuller-stack-dev

Copy link
Copy Markdown
Member

Summary

  • replace selective tar snapshots with verified whole-environment-root checkpoints
  • use APFS clones when available, with metadata-preserving full-copy fallback
  • quiesce managed gateways for snapshot capture and restore
  • restore through an exclusive same-filesystem operation namespace
  • retain rejected restored roots before atomically reinstating displaced roots
  • keep legacy tar snapshot metadata readable and restorable
  • use the same complete snapshot transaction for coherent upgrade rollback

This builds on the whole-root checkpoint and cold-lifecycle direction explored by @hannesrudolph in #60, while keeping that PR's broader companion, build-local, and supervisor-policy work out of this change.

Problem

Current snapshots archive selected OpenClaw paths but restore by replacing the complete environment root. On d1c36adda05c1129af9788be35528bc1240d95da, restoring a snapshot deleted .openclaw/.env, secrets, unknown future state, and symlinks that the archive omitted. A foreign directory matching the predictable restore-backup name also caused restore to fail.

Transaction invariant

The displaced pre-restore root remains recoverable until service acceptance succeeds. If acceptance fails, OCM:

  1. renames the rejected restored root into the operation-owned namespace
  2. atomically renames the displaced root back into place
  3. restores the original registry state
  4. resynchronizes the supervisor
  5. cleans operation-owned rejected/orphan paths afterward

Scope

This PR deliberately excludes runtime build-local changes, supervisor convergence retry policy, companion management, and unrelated cleanup. It preserves the runtime mutation and rollback ordering from #66.

Validation

  • base red: complete-root data loss and predictable foreign-path collision reproduced on d1c36adda05c1129af9788be35528bc1240d95da
  • cargo test --locked -- --test-threads=1
  • cargo check --workspace --all-targets --locked
  • cargo clippy --workspace --all-targets --all-features --locked -- -D warnings -A clippy::question_mark -A clippy::large_enum_variant -A clippy::too_many_arguments
  • cargo fmt --check
  • git diff --check
  • environment snapshot suite: 31/31
  • store flow suite: 29/29
  • upgrade suite: 44/44
  • fix(upgrade): quiesce runtime rollback mutations #66 regression: failed_named_runtime_target_in_backoff_is_not_rewritten_during_rollback
  • source-blind behavior contract: complete root, modes, symlinks, SQLite, corrupt SQLite rejection, opaque .db, foreign collision, failed acceptance rollback, legacy tar, and failed-upgrade rollback all passed
  • autoreview: clean; TruffleHog clean

Isolated synthetic Rosita-shaped benchmark, without reading or touching live Rosita:

  • 6,006 files
  • 168,154,957 logical bytes
  • APFS clone checkpoint storage
  • three cold captures
  • median capture plus verification: 2.526 seconds
  • median managed-gateway stopped window: 2.392 seconds

@fuller-stack-dev
fuller-stack-dev merged commit 5971574 into openclaw:main Aug 11, 2026
5 checks passed
@fuller-stack-dev

Copy link
Copy Markdown
Member Author

Merged as 5971574bd605b82fd22238845ecbe9db74baa841 after exact-head CI passed on macOS, Ubuntu, Windows, formatting, and Rust 1.88.

@fuller-stack-dev
fuller-stack-dev deleted the fix/atomic-whole-root-snapshots branch August 11, 2026 19:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant