Lab Specification — Module 8: State, Checkpointing & Multi-Session

Module: 8 · Duration: 40 min · Environment: Codespace, Node 18+.

Learning objectives

  1. Implement atomic checkpoint writes (temp + rename).
  2. Kill the process mid-task; verify resume from last checkpoint with no duplicated side effects.
  3. Build a 3-session task that pauses between sessions via checkpoints.

Phase 1 — Atomic checkpoint (15 min)

import { writeFileSync, renameSync, readFileSync, existsSync } from "fs";
function atomicCheckpoint(path: string, state: any) {
  const tmp = path + ".tmp";
  writeFileSync(tmp, JSON.stringify(state));
  renameSync(tmp, path);  // ATOMIC on POSIX
}
function loadCheckpoint(path: string): any | null {
  return existsSync(path) ? JSON.parse(readFileSync(path, "utf-8")) : null;
}

Verify: write a checkpoint; read it back; confirm round-trip. Then simulate a crash mid-temp-write (delete the .tmp before rename); confirm the OLD checkpoint is intact.

Phase 2 — Crash recovery (10 min)

Run a 10-step task that checkpoints after each step. Kill the process at step 6 (Ctrl+C or process.exit()). Re-run: the harness reads the checkpoint, resumes at step 6, completes 6–10. Verify no step ran twice (add a side-effect counter).

Phase 3 — 3-session task (15 min)

Build a task that: Session 1 does steps 1–4, checkpoints, exits. Session 2 reads checkpoint, does 5–8, checkpoints, exits. Session 3 reads checkpoint, does 9–10, completes. All three sessions are separate process invocations.

Deliverables

Stretch goals

  1. Git-backed checkpoints: commit after each step; on crash, git reset --hard <last-commit> to recover. Compare to the file-based checkpoint.
  2. Session diffing: run the same task with two different prompts; diff the checkpoints to find where behavior diverged.
# Lab Specification — Module 8: State, Checkpointing & Multi-Session

**Module**: 8 · **Duration**: 40 min · **Environment**: Codespace, Node 18+.

## Learning objectives
1. Implement **atomic checkpoint writes** (temp + rename).
2. **Kill the process mid-task**; verify resume from last checkpoint with no duplicated side effects.
3. Build a **3-session task** that pauses between sessions via checkpoints.

## Phase 1 — Atomic checkpoint (15 min)
```typescript
import { writeFileSync, renameSync, readFileSync, existsSync } from "fs";
function atomicCheckpoint(path: string, state: any) {
  const tmp = path + ".tmp";
  writeFileSync(tmp, JSON.stringify(state));
  renameSync(tmp, path);  // ATOMIC on POSIX
}
function loadCheckpoint(path: string): any | null {
  return existsSync(path) ? JSON.parse(readFileSync(path, "utf-8")) : null;
}
```
**Verify**: write a checkpoint; read it back; confirm round-trip. Then simulate a crash mid-temp-write (delete the .tmp before rename); confirm the OLD checkpoint is intact.

## Phase 2 — Crash recovery (10 min)
Run a 10-step task that checkpoints after each step. Kill the process at step 6 (Ctrl+C or `process.exit()`). Re-run: the harness reads the checkpoint, resumes at step 6, completes 6–10. **Verify no step ran twice** (add a side-effect counter).

## Phase 3 — 3-session task (15 min)
Build a task that: Session 1 does steps 1–4, checkpoints, exits. Session 2 reads checkpoint, does 5–8, checkpoints, exits. Session 3 reads checkpoint, does 9–10, completes. All three sessions are separate process invocations.

## Deliverables
- [ ] Phase 1: atomic write code + crash-safety test (old checkpoint intact after interrupted temp-write)
- [ ] Phase 2: side-effect counter showing no step ran twice after crash+resume
- [ ] Phase 3: 3 sessions completing a 10-step task across process boundaries

## Stretch goals
1. **Git-backed checkpoints**: commit after each step; on crash, `git reset --hard <last-commit>` to recover. Compare to the file-based checkpoint.
2. **Session diffing**: run the same task with two different prompts; diff the checkpoints to find where behavior diverged.