Files
wehub-resource-sync 9f2e1cd2af
Ruby / Ruby 4.0.5 (push) Failing after 5m13s
Ruby / Ruby 3.3.4 (push) Failing after 5m43s
Ruby / Ruby 2.6.8 (push) Failing after 16m2s
chore: import upstream snapshot with attribution
2026-07-13 12:33:07 +08:00

8.8 KiB

Time Machine Design Documentation

Overview

Time Machine is a feature that allows users to navigate through the agent's task execution history, providing undo/redo capabilities and branch exploration. Users can access it via ESC key or /undo command to view an interactive menu of past tasks.

Core Data Structure Design

Task History Graph

The Time Machine uses a minimal tree-based data structure to track task relationships:

Three Core State Variables:

  1. task_parents (Hash): Maps each task_id to its parent_id

    • Forms a tree structure where each task points to its predecessor
    • Root tasks have parent_id = 0
    • Enables traversal in both directions (parent→children, child→parent)
  2. current_task_id (Integer): The latest created task ID

    • Always increments when new tasks are created
    • Never decreases, even during undo operations
    • Represents the "tip" of the execution timeline
  3. active_task_id (Integer): The current active position in history

    • Can move backward/forward during undo/redo
    • Determines which messages are visible to the LLM
    • When active_task_id < current_task_id, we're viewing "past" state

Task Metadata Structure

Each task in the history contains:

  • task_id: Unique identifier (auto-incrementing integer)
  • summary: Brief description (first 80 chars of user's message)
  • status: One of three states
    • :past - Task is before the current active position
    • :current - Task is the active position (marked with )
    • :future - Task exists but is after active position (marked with )
  • has_branches: Boolean indicating if multiple children exist (marked with )

Snapshot Strategy

File State Preservation

Complete AFTER-State Snapshots:

  • After each successful task execution, all modified files are saved
  • Storage location: ~/.clacky/snapshots/{session_id}/task-{id}/
  • Each file is stored with its full relative path from working directory
  • Only files modified during that task are snapshotted

Why AFTER-state instead of BEFORE-state:

  • Simpler restoration logic (just copy files back)
  • No need to track "what changed" - the snapshot IS the state
  • Easier to verify correctness (snapshot = expected state)

File Restoration Process:

  • When switching to a task, iterate through all its snapshotted files
  • Copy each file from snapshot directory to working directory
  • File permissions and timestamps are preserved

Message Filtering

Active Messages Concept:

  • Messages array contains ALL messages (past, current, future)
  • active_messages() method filters out "future" messages
  • LLM only sees messages with task_id <= active_task_id
  • This creates the illusion of time travel without data deletion

Why Keep All Messages:

  • Enables redo operations (future messages preserved)
  • Allows branch switching (alternative futures available)
  • Simplifies session serialization (single source of truth)

Session Persistence

State Serialization

Time Machine state is saved under :time_machine key in session data:

  • task_parents hash (complete tree structure)
  • current_task_id (latest task number)
  • active_task_id (current viewing position)

Restoration Guarantees:

  • Complete task tree is rebuilt
  • Active position is restored
  • Snapshot files remain available across sessions
  • User can continue undo/redo from where they left off

Critical Test Scenarios

1. Basic Undo/Redo Flow

Test Focus:

  • Sequential task creation increments task IDs correctly
  • Undo moves active_task_id backward (current_task_id unchanged)
  • Redo moves active_task_id forward
  • File snapshots are correctly restored at each step
  • Cannot undo beyond root task (task_id = 0)
  • Cannot redo beyond current_task_id

Edge Cases:

  • Undoing at root task should fail gracefully
  • Redoing when already at tip should fail gracefully
  • Multiple consecutive undos should work correctly

2. Branching Scenarios

Test Focus:

  • After undo, creating new task creates a branch
  • New branch starts from active_task_id, not current_task_id
  • Original future branch is preserved (for potential redo)
  • Parent task is marked with has_branches: true
  • Child tasks list should include both branches

Branch Navigation:

  • Switching between branches restores correct file states
  • Each branch maintains independent history
  • Message filtering correctly shows only relevant messages

3. Message Filtering and Task IDs

Test Focus:

  • Every message is tagged with task_id (user, assistant, tool results)
  • Active messages only include those with task_id <= active_task_id
  • LLM never sees "future" messages during undo state
  • After redo, future messages become visible again
  • New tasks created after undo get fresh task IDs (not reused)

Message Consistency:

  • Tool results are associated with correct task
  • Multi-turn conversations maintain task association
  • Error messages don't break task ID tagging

4. File Snapshot Integrity

Test Focus:

  • Only modified files are snapshotted (not entire project)
  • File content is exactly preserved (byte-for-byte)
  • Nested directory structures are correctly recreated
  • Multiple files in single task are all snapshotted
  • Snapshot directory naming prevents collisions

Restoration Accuracy:

  • After undo + file restore, file content matches expected state
  • Subsequent task execution works with restored files
  • Binary files are handled correctly (not corrupted)

5. Session Persistence and Recovery

Test Focus:

  • Save session, restart, restore session preserves Time Machine state
  • Task tree structure is fully rebuilt
  • Active position is correctly restored
  • Snapshot files are accessible after restart
  • Undo/redo operations work identically after restore

Persistence Edge Cases:

  • Empty task history (new session)
  • Session with complex branching
  • Session saved while in "undo" state (active_task_id < current_task_id)

6. AI Tool Integration

Test Focus:

  • Tools are correctly registered in tool registry
  • AI can invoke undo_task, redo_task, list_tasks
  • Agent parameter is correctly injected (similar to TodoManager pattern)
  • Tool execution returns success/failure messages
  • Tools respect permission modes (confirm_all, auto_approve, etc.)

Tool Interaction:

  • AI calling undo_task modifies agent state correctly
  • Subsequent AI responses use filtered messages
  • Tool results are included in task history
  • Multiple tool calls in sequence work correctly

7. UI and User Interaction

Test Focus:

  • ESC key triggers time machine menu
  • /undo command works identically to ESC
  • Menu displays correct task list with status indicators
  • Visual markers: current, future, branches
  • User selection triggers correct task switch
  • Menu updates after undo/redo operations

User Experience:

  • Task summaries are readable (truncated to 80 chars)
  • Menu is responsive with large task histories
  • Cancel/exit returns to normal operation
  • Error messages are clear and actionable

8. Integration with Existing Features

Test Focus:

  • Works with message compression (no dependency on tool_calls)
  • Compatible with session serialization
  • Doesn't interfere with cost tracking
  • Works with both UI modes (UI1 and UI2)
  • Subagent forking doesn't inherit Time Machine state

Feature Compatibility:

  • Todo manager works normally during undo state
  • Web search tools work correctly
  • File tools (write, edit) trigger snapshots
  • Shell commands can be undone via file snapshots

Design Principles

Minimal Invasiveness

  • Only 3 new instance variables in Agent class
  • No changes to core message structure (only adds task_id field)
  • Existing tools unaware of Time Machine existence
  • No performance impact when not in use

Data Integrity

  • Never delete messages or snapshots (immutable history)
  • File restoration is idempotent (can redo multiple times)
  • Task IDs never reused (prevents confusion)
  • Snapshot isolation (each task has independent directory)

User Control

  • Explicit user action required (ESC or /undo)
  • Clear visual feedback on current position
  • Cannot accidentally lose work (future preserved)
  • Can explore branches without commitment

Developer Friendly

  • Simple tree data structure (easy to reason about)
  • Comprehensive test coverage (55 test cases)
  • Clear separation of concerns (module-based design)
  • Well-documented edge cases

Future Enhancement Possibilities

Potential Improvements

  • Automatic snapshot garbage collection (old sessions)
  • Diff view between task states
  • Named checkpoints (user-defined bookmarks)
  • Merge branches functionality
  • Export task history as replay script
  • Snapshot compression for large files

Scalability Considerations

  • Large file handling (incremental snapshots)
  • Long session histories (pagination in UI)
  • Multiple simultaneous branches (better visualization)
  • Remote collaboration (shared task history)