Loading...
Loading...
State persistence patterns for autonomous-dev including JSON persistence, atomic writes, file locking, crash recovery, and state versioning. Use when implementing stateful libraries or features requiring persistent state.
npx skill4agent add vuralserhat86/antigravity-agentic-skills state_managementimport json
from pathlib import Path
from typing import Dict, Any
import tempfile
import os
def save_state_atomic(state: Dict[str, Any], state_file: Path) -> None:
"""Save state with atomic write to prevent corruption.
Args:
state: State dictionary to persist
state_file: Target state file path
Security:
- Atomic Write: Prevents partial writes on crash
- Temp File: Write to temp, then rename (atomic operation)
- Permissions: Preserves file permissions
"""
# Write to temporary file first
temp_fd, temp_path = tempfile.mkstemp(
dir=state_file.parent,
prefix=f".{state_file.name}.",
suffix=".tmp"
)
try:
# Write JSON to temp file
with os.fdopen(temp_fd, 'w') as f:
json.dump(state, f, indent=2)
# Atomic rename (overwrites target)
os.replace(temp_path, state_file)
except Exception:
# Clean up temp file on failure
if Path(temp_path).exists():
Path(temp_path).unlink()
raisedocs/json-persistence.mdexamples/batch-state-example.pyimport fcntl
import json
from pathlib import Path
from contextlib import contextmanager
@contextmanager
def file_lock(filepath: Path):
"""Acquire exclusive file lock for state file.
Args:
filepath: Path to file to lock
Yields:
Open file handle with exclusive lock
Example:
>>> with file_lock(state_file) as f:
... state = json.load(f)
... state['count'] += 1
... f.seek(0)
... f.truncate()
... json.dump(state, f)
"""
with filepath.open('r+') as f:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
try:
yield f
finally:
fcntl.flock(f.fileno(), fcntl.LOCK_UN)docs/file-locking.mdtemplates/file-lock-template.py@dataclass
class BatchState:
"""Batch processing state with crash recovery support.
Attributes:
batch_id: Unique batch identifier
features: List of all features to process
current_index: Index of current feature
completed: List of completed feature names
failed: List of failed feature names
created_at: State creation timestamp
last_updated: Last update timestamp
"""
batch_id: str
features: List[str]
current_index: int = 0
completed: List[str] = None
failed: List[str] = None
created_at: str = None
last_updated: str = None
def __post_init__(self):
if self.completed is None:
self.completed = []
if self.failed is None:
self.failed = []
if self.created_at is None:
self.created_at = datetime.now().isoformat()
self.last_updated = datetime.now().isoformat()docs/crash-recovery.mdexamples/crash-recovery-example.pySTATE_VERSION = "2.0.0"
def migrate_state(state: Dict[str, Any]) -> Dict[str, Any]:
"""Migrate state from old version to current.
Args:
state: State dictionary (any version)
Returns:
Migrated state (current version)
"""
version = state.get("version", "1.0.0")
if version == "1.0.0":
# Migrate 1.0.0 → 1.1.0
state = _migrate_1_0_to_1_1(state)
version = "1.1.0"
if version == "1.1.0":
# Migrate 1.1.0 → 2.0.0
state = _migrate_1_1_to_2_0(state)
version = "2.0.0"
state["version"] = STATE_VERSION
return statedocs/state-versioning.mdtemplates/state-manager-template.pyplugins/autonomous-dev/lib/batch_state_manager.py# Create batch state
manager = BatchStateManager.create(["feat1", "feat2", "feat3"])
manager.batch_id # "batch-20251116-123456"
# Process features
for feature in manager.features:
if manager.should_clear_context():
# Clear context at 150K tokens
manager.record_context_clear()
try:
# Process feature
result = process_feature(feature)
manager.mark_completed(feature)
except Exception as e:
manager.mark_failed(feature, str(e))
manager.save() # Atomic write
# Resume after crash
manager = BatchStateManager.load("batch-20251116-123456")
next_feature = manager.get_next_feature() # Skips completedfrom pathlib import Path
import sys
# Portable path detection
current = Path.cwd()
while current != current.parent:
if (current / ".git").exists():
project_root = current
break
current = current.parent
# Add lib to path
lib_path = project_root / "plugins/autonomous-dev/lib"
if lib_path.exists():
sys.path.insert(0, str(lib_path))
try:
from agent_tracker import AgentTracker
success = AgentTracker.save_agent_checkpoint(
agent_name='my-agent',
message='Task completed - found 5 patterns',
tools_used=['Read', 'Grep', 'WebSearch']
)
print(f"Checkpoint: {'saved' if success else 'skipped'}")
except ImportError:
print("ℹ️ Checkpoint skipped (user project)")templates/templates/state-manager-template.pytemplates/atomic-write-template.pytemplates/file-lock-template.pyexamples/batch-state-example.pyexamples/user-state-example.pyexamples/crash-recovery-example.pydocs/json-persistence.mddocs/atomic-writes.mddocs/file-locking.mddocs/crash-recovery.mdskills/library-design-patterns/skills/error-handling-patterns/useStateContextZustandRedux Toolkitpersistselectors| Aşama | Doğrulama |
|---|---|
| 1 | State objesi doğrudan mutasyona uğratılıyor mu? (Immutability kontrolü) |
| 2 | State hiyerarşisi "Prop Drilling" problemine yol açıyor mu? |
| 3 | Loading ve Error state'leri kullanıcıya doğru şekilde yansıtılıyor mu? |