Rollback to a checkpoint. Args: checkpoint_id: Checkpoint ID to rollback to Returns: True if rollback successful
(checkpoint_id: str)
| 188 | |
| 189 | |
| 190 | def rollback(checkpoint_id: str) -> bool: |
| 191 | """ |
| 192 | Rollback to a checkpoint. |
| 193 | |
| 194 | Args: |
| 195 | checkpoint_id: Checkpoint ID to rollback to |
| 196 | |
| 197 | Returns: |
| 198 | True if rollback successful |
| 199 | """ |
| 200 | backup_dir = CHECKPOINT_DIR / checkpoint_id |
| 201 | |
| 202 | if not backup_dir.exists(): |
| 203 | error(f"Rollback: checkpoint '{checkpoint_id}' not found") |
| 204 | return False |
| 205 | |
| 206 | info(f"Rollback: restoring from '{checkpoint_id}'") |
| 207 | |
| 208 | # Restore files from backup |
| 209 | restored = 0 |
| 210 | for backup_file in backup_dir.rglob("*"): |
| 211 | if backup_file.is_file(): |
| 212 | try: |
| 213 | rel_path = backup_file.relative_to(backup_dir) |
| 214 | dest = CODE_DIR / rel_path |
| 215 | dest.parent.mkdir(parents=True, exist_ok=True) |
| 216 | shutil.copy2(backup_file, dest) |
| 217 | restored += 1 |
| 218 | except Exception as e: |
| 219 | error(f"Rollback: could not restore {backup_file}: {e}") |
| 220 | |
| 221 | # Try to git checkout the commit |
| 222 | state = get_state_store() |
| 223 | checkpoint_data = state.get_checkpoint(checkpoint_id) |
| 224 | |
| 225 | if checkpoint_data and checkpoint_data.get("git_commit_hash"): |
| 226 | git_hash = checkpoint_data["git_commit_hash"] |
| 227 | try: |
| 228 | subprocess.run( |
| 229 | ["git", "checkout", git_hash], |
| 230 | cwd=CODE_DIR, |
| 231 | capture_output=True |
| 232 | ) |
| 233 | info(f"Rollback: checked out git commit {git_hash[:8]}") |
| 234 | except Exception as e: |
| 235 | warning(f"Rollback: git checkout failed: {e}") |
| 236 | |
| 237 | success(f"Rollback: restored {restored} files from checkpoint '{checkpoint_id}'") |
| 238 | |
| 239 | # Log in episodic memory |
| 240 | state.log_action("rollback", f"Restored from checkpoint {checkpoint_id}") |
| 241 | |
| 242 | return True |
| 243 | |
| 244 | |
| 245 | def list_checkpoints(limit: int = 10) -> List[Dict]: |
nothing calls this directly
no test coverage detected