This repository has been archived on 2026-08-07. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
openclaw/skills/gsd-openclaw/.planning/phases/01-core-infrastructure/01-01-PLAN.md
T

9.4 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
phase plan type wave depends_on files_modified autonomous requirements user_setup must_haves
01-core-infrastructure 01 execute 1
src/gsd_openclaw/__init__.py
src/gsd_openclaw/state_manager.py
tests/conftest.py
tests/test_state_manager.py
true
SESS-04
truths artifacts key_links
State can be saved to JSON file atomically
State can be loaded from JSON file
Corrupted state falls back to backup automatically
State schema includes session metadata, tmux references, and activity stats
path provides exports min_lines
src/gsd_openclaw/state_manager.py State persistence with atomic writes
SessionState
StateManager
save_state
load_state
80
path provides contains
tests/test_state_manager.py Test coverage for state operations test_save_load_state
from to via pattern
src/gsd_openclaw/state_manager.py ~/gsd-workspaces/{project}/.gsd/state.json atomic write (tempfile + os.replace) tempfile.mkstemp.*os.replace
Implement state persistence layer with atomic writes and backup rotation for crash-safe session checkpointing.

Purpose: Provides the foundation for all session state management. Other components depend on this for storing and recovering session metadata.

Output: Working state_manager.py with atomic save, load with validation, and automatic backup rotation.

<execution_context> @/home/starmen1265/.claude/get-shit-done/workflows/execute-plan.md @/home/starmen1265/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-core-infrastructure/01-CONTEXT.md @.planning/phases/01-core-infrastructure/01-RESEARCH.md @.planning/phases/01-core-infrastructure/01-VALIDATION.md

SessionState dataclass:

@dataclass
class SessionState:
    schema_version: str = "1.0"
    session_id: str = ""
    project_name: str = ""
    tmux_session_name: str = ""
    tmux_pane_id: str = ""
    created_at: str = ""
    last_active_at: str = ""
    command_count: int = 0
    last_output_snapshot: Optional[str] = None
    display_name: Optional[str] = None

Atomic write pattern:

def save_state(state: dict, state_path: Path) -> None:
    fd, temp_path = tempfile.mkstemp(dir=state_path.parent, suffix='.tmp')
    try:
        with os.fdopen(fd, 'w', encoding='utf-8') as f:
            json.dump(state, f, indent=2, ensure_ascii=False)
        os.replace(temp_path, state_path)
    except Exception:
        if os.path.exists(temp_path):
            os.unlink(temp_path)
        raise
Task 1: Create state schema with dataclasses src/gsd_openclaw/__init__.py, src/gsd_openclaw/state_manager.py - Test 1: SessionState can be created with all fields - Test 2: SessionState.to_dict() returns complete dict - Test 3: SessionState.from_dict() reconstructs from dict - Test 4: SessionState ignores unknown fields in from_dict() Create the SessionState dataclass with all fields from CONTEXT.md: - schema_version (default "1.0") - session_id, project_name, tmux_session_name, tmux_pane_id - created_at, last_active_at (ISO format strings) - command_count (int) - last_output_snapshot, display_name (Optional[str])

Implement to_dict() using dataclasses.asdict() and from_dict() with field filtering.

Also create the package __init__.py with version and exports.

Do NOT add validation logic yet - that comes in Task 3. pytest tests/test_state_manager.py::test_session_state_creation -x pytest tests/test_state_manager.py::test_session_state_serialization -x SessionState dataclass exists with all fields, to_dict() and from_dict() methods work correctly

Task 2: Implement atomic state save with backup rotation src/gsd_openclaw/state_manager.py, tests/test_state_manager.py - Test 1: save_state creates file atomically (temp file + rename) - Test 2: save_state creates parent directories if missing - Test 3: save_state rotates backup (state.json -> state.json.bak) - Test 4: save_state cleans up temp file on failure - Test 5: Temp file is created in same directory as target (for atomic rename) Implement save_state(state: SessionState, state_path: Path) function:
  1. Create parent directories with mkdir(parents=True, exist_ok=True)
  2. If state_path exists, rotate backup:
    • Delete old state.json.bak if exists
    • Rename state_path to state.json.bak
  3. Write to temp file using tempfile.mkstemp(dir=state_path.parent, suffix='.tmp')
  4. Use os.fdopen to write JSON with indent=2, ensure_ascii=False
  5. Atomic replace with os.replace(temp_path, state_path)
  6. On exception, clean up temp file if it exists

Use the pattern from RESEARCH.md - this is the atomic write pattern proven to prevent corruption.

Do NOT use file locking - os.replace is atomic on POSIX systems. pytest tests/test_state_manager.py::test_atomic_write -x pytest tests/test_state_manager.py::test_backup_rotation -x State saves atomically, backup rotates correctly, temp files cleaned up on failure

Task 3: Implement state load with validation and fallback src/gsd_openclaw/state_manager.py, tests/test_state_manager.py, tests/conftest.py - Test 1: load_state returns None for missing file - Test 2: load_state returns SessionState for valid file - Test 3: load_state raises ValueError for unsupported schema version - Test 4: load_state raises ValueError for missing required fields - Test 5: load_state falls back to backup when main file is corrupted (JSONDecodeError) - Test 6: load_state falls back to backup when validation fails Implement load_state(state_path: Path) -> Optional[SessionState] function:
  1. If state_path doesn't exist, try backup (state_path.with_suffix('.json.bak'))
  2. If neither exists, return None
  3. Read JSON with proper encoding (utf-8)
  4. Validate:
    • schema_version == "1.0" (raise ValueError if not)
    • Required fields present: session_id, project_name, tmux_session_name
  5. On JSONDecodeError or ValueError, try backup (if backup != state_path)
  6. Return SessionState.from_dict(data)

Also create tests/conftest.py with pytest fixtures:

  • tmp_state_dir fixture using pytest's tmp_path
  • sample_state fixture returning a valid SessionState instance pytest tests/test_state_manager.py::test_save_load_state -x pytest tests/test_state_manager.py::test_state_validation -x pytest tests/test_state_manager.py::test_backup_fallback -x State loads with validation, corrupted files fall back to backup, missing files return None
Task 4: Create StateManager class with workspace path resolution src/gsd_openclaw/state_manager.py, tests/test_state_manager.py - Test 1: StateManager.get_state_path returns correct path for project - Test 2: StateManager.save persists state to correct location - Test 3: StateManager.load retrieves state from correct location Create StateManager class that encapsulates state operations:
class StateManager:
    WORKSPACES_ROOT = Path.home() / "gsd-workspaces"

    def __init__(self, project_name: str):
        self.project_name = project_name
        self.workspace_path = self.WORKSPACES_ROOT / project_name
        self.state_path = self.workspace_path / ".gsd" / "state.json"

    def save(self, state: SessionState) -> None:
        save_state(state, self.state_path)

    def load(self) -> Optional[SessionState]:
        return load_state(self.state_path)

    def get_state_path(self) -> Path:
        return self.state_path

This provides a clean interface for other components to use state persistence without managing paths directly. pytest tests/test_state_manager.py::test_state_manager_class -x StateManager class provides clean interface for state persistence with correct workspace paths

Run full test suite to verify all state operations: ```bash pytest tests/test_state_manager.py -v ```

All tests must pass. Coverage should include:

  • Atomic write pattern
  • Backup rotation
  • Validation logic
  • Fallback to backup
  • StateManager convenience methods

<success_criteria>

  • SessionState dataclass with all required fields exists
  • Atomic save_state function prevents corruption
  • load_state validates schema and required fields
  • Backup rotation works (state.json.bak)
  • Corrupted files fall back to backup automatically
  • StateManager class provides clean interface
  • All tests pass: pytest tests/test_state_manager.py -v </success_criteria>
After completion, create `.planning/phases/01-core-infrastructure/01-01-SUMMARY.md`