Lesson 07 · Memory

State written to disk, survives compression

"State that survives compression - because it's outside the conversation."

⏱ ~10 min · 📝 3 interactive widgets · 🧑‍💻 Based on shareAI-lab · s07_task_system.py

What is the difference between TodoWrite and Task?

s03's TodoManager can also list tasks - but it stores them in memory. When s06's auto_compact fires and replaces messages[] with a summary, the TodoManager state disappears with it (because it's in-memory).

s07's Task is different: each task is a .tasks/task_42.json file. Context compacted, process restarted, agent swapped out - as long as the file is on disk, the task survives.

# .tasks/task_12.json
{
  "id": 12,
  "subject": "Refactor auth middleware",
  "description": "Extract JWT logic to shared module",
  "status": "pending",
  "blockedBy": [8, 11],   # must complete #8 and #11 first
  "owner": ""
}
Rule of thumb: Use todo for ephemeral tasks (forget after this session). Use task for persistent work (cross-session, with dependencies).

blockedBy: the dependency graph

blockedBy is a list of task IDs - the current task can't execute until all of them are completed.

s07's implementation has an elegant detail: when a task is completed, it automatically removes itself from all other tasks' blockedBy lists.

def _clear_dependency(self, completed_id: int):
    # Scan every task, remove completed_id from their blockedBy
    for f in self.dir.glob("task_*.json"):
        task = json.loads(f.read_text())
        if completed_id in task.get("blockedBy", []):
            task["blockedBy"].remove(completed_id)
            self._save(task)

The agent never needs a separate "which tasks just unblocked" table. Just scan .tasks/, find entries where status=="pending" and not blockedBy - those are the ready tasks.

Dependency graph interaction

The widget below gives you a 5-task dependency graph. Click "complete" and watch blockedBy update automatically, turning some tasks green (ready to execute).

Does it survive compression?

s06 showed that auto_compact replaces messages[] with a single summary. But tasks are unaffected - they're on disk. Test it: have the agent create 5 tasks, compact the conversation, then scan .tasks/ to resume.

Interactive

Widget 1 · Dependency Graph · click complete and watch dependencies update

5 tasks with a topological relationship. Click Start or Complete on any task, and watch the blockedBy arrays and ready-to-execute list update.

Task list (.tasks/ directory)
Currently executable (status=pending, blockedBy=[])
Dependency graph
Interactive

Widget 2 · Compression Survival · tasks outlive auto_compact

Have the agent create 3 tasks, trigger auto_compact (messages cleared), then recover - see whether the tasks still exist.

.tasks/ directory
messages[]
Interactive

Widget 3 · Dependency Chain · which tasks are executable right now?

5 tasks with dependencies. Given the current state, identify which tasks are ready to start (may be multiple).

Correct: 0 / 4