Features
Git Checkpoints

Git Checkpoints

Safe experimentation through intelligent git snapshots.

Git checkpoints let you try multiple approaches fearlessly. When approach A doesn't work, restore your baseline and try approach Bβ€”without losing any work. Think of them as save points in a video game, but for your code.

The Problem: Fear of Experimentation

Without checkpoints, trying different approaches is risky:

YOU: "Try implementing authentication with both JWT and sessions to see which works better."

Without Checkpoints:
  Try JWT β†’ Doesn't work well β†’ Manual git reset β†’ Lost time
  Manually restore files β†’ Hope you didn't miss anything β†’ Start over

With Checkpoints:
  Create checkpoint β†’ Try JWT β†’ Doesn't work β†’ Restore checkpoint β†’ Try sessions β†’ Works! βœ“

The difference: Checkpoints make experimentation instant and safe.

How Checkpoints Work

Checkpoints use git's stash mechanism under the hood, but with intelligent automation and naming:

Key Features:

  • Non-invasive: Your working directory stays untouched during checkpoint creation
  • Comprehensive: Captures all modified files, staged files, and untracked files
  • Organized: Stored in custom git refs for easy management
  • Re-restorable: Use the same checkpoint multiple times for different experiments

Two Types of Checkpoints

Automatic Checkpoints (πŸ€–)

Created automatically before every workflow state transition (except from backlog).

Naming pattern: {work-unit-id}-auto-{previous-state}

Example conversation:

YOU: "Move AUTH-001 to implementing."

AI: Moving AUTH-001 from testing to implementing...
    πŸ€– Auto-checkpoint: "AUTH-001-auto-testing" created before transition
    βœ“ Work unit AUTH-001 status updated to implementing

    This checkpoint captures your work from the testing phase.
    If anything goes wrong in implementing, you can restore it.

When created:

  • specifying β†’ testing: Creates AUTH-001-auto-specifying
  • testing β†’ implementing: Creates AUTH-001-auto-testing
  • implementing β†’ validating: Creates AUTH-001-auto-implementing
  • validating β†’ done: Creates AUTH-001-auto-validating, then cleans up all auto-checkpoints

Why automatic checkpoints matter:

  • Recovery from mistakes during implementation
  • Rollback if new status proves premature
  • Safety net for AI-driven changes
  • No need to remember to create them

Manual Checkpoints (πŸ“Œ)

Created explicitly when you need to experiment or create a baseline.

Usage:

fspec checkpoint AUTH-001 baseline
fspec checkpoint AUTH-001 before-refactor
fspec checkpoint AUTH-001 experiment-jwt

Example conversation:

YOU: "Let's try a different approach to authentication. Create a checkpoint first."

AI: Creating checkpoint to preserve current state...
    πŸ“Œ Manual checkpoint: "baseline" created for AUTH-001

    Now I can safely experiment. If the new approach doesn't work,
    I'll restore "baseline" and try something else.

When to create manual checkpoints:

  • Before trying multiple experimental approaches
  • Before risky refactoring
  • When creating a baseline for comparison
  • Before making architectural changes

The Checkpoint Lifecycle

Creation Phase

What happens when you create a checkpoint:

  1. Check for changes: Working directory must have uncommitted changes
  2. Stage files: All modified, untracked files are staged temporarily
  3. Create stash: Git creates a stash commit (your code is saved)
  4. Store reference: Custom ref stores the checkpoint ID
  5. Index update: Fast lookup index is updated
  6. Clean staging area: Staging area reset (no pollution)
  7. Notify: System notifies you of successful creation

Storage locations:

  • Git objects: .git/objects/ (actual file content)
  • Checkpoint refs: .git/refs/fspec-checkpoints/{work-unit-id}/{name}
  • Index files: .git/fspec-checkpoints-index/{work-unit-id}.json

Restoration Phase

What happens when you restore a checkpoint:

  1. Check working directory: Are there uncommitted changes?
  2. Handle dirty state: If dirty, prompt for action (commit, stash, or force)
  3. Resolve checkpoint: Find the checkpoint in git refs
  4. Detect conflicts: Compare current files with checkpoint files
  5. Restore files: Overwrite current files with checkpoint versions
  6. Delete new files: Remove files created after checkpoint
  7. Notify: Confirm restoration success

Natural Language Workflows

Scenario 1: Multiple Experimental Approaches

YOU: "Try three different caching strategies: Redis, Memcached, and in-memory.
     Keep whichever performs best."

AI: I'll create a baseline checkpoint before trying different approaches...
    πŸ“Œ Checkpoint "baseline" created for PERF-042

    Trying Redis first...
    [implements Redis caching]
    [runs benchmarks]

    Redis: 150ms average response time
    Let me try Memcached...

    Restoring baseline...
    βœ“ Restored checkpoint "baseline"

    Trying Memcached...
    [implements Memcached caching]
    [runs benchmarks]

    Memcached: 120ms average response time
    Let me try in-memory...

    Restoring baseline...
    βœ“ Restored checkpoint "baseline"

    Trying in-memory caching...
    [implements in-memory caching]
    [runs benchmarks]

    In-memory: 80ms average response time βœ“ BEST!

    In-memory caching is fastest. I'll keep this implementation.

YOU: "Perfect! Clean up the old checkpoints."

AI: Cleaning up experiment checkpoints...
    fspec cleanup-checkpoints PERF-042 --keep-last 2

    βœ“ Deleted 2 checkpoint(s): redis-attempt, memcached-attempt
    βœ“ Kept 2 checkpoint(s): in-memory-final, baseline

Scenario 2: Risky Refactoring with Safety Net

YOU: "Refactor the entire authentication middleware to use decorators."

AI: This is a significant refactoring. Creating checkpoint first...
    πŸ“Œ Checkpoint "before-decorator-refactor" created for AUTH-001

    Beginning decorator refactoring...
    [major code restructuring]
    [runs tests]

    βœ— Tests failed: Decorators broke the routing system

AI: The decorator approach has issues. Restoring previous state...
    βœ“ Restored checkpoint "before-decorator-refactor"

    Let me try a less invasive approach - extracting helper functions instead...
    [implements helper function extraction]
    [runs tests]

    βœ“ Tests pass! This approach works better.

Scenario 3: Handling Dirty Working Directory

YOU: "Restore the baseline checkpoint."

AI: Attempting to restore checkpoint "baseline"...

    ⚠️  Working directory has uncommitted changes

    I have these options:
    1. Commit changes first [Low risk] - Safest
    2. Stash changes and restore [Medium risk] - Saves for later
    3. Overwrite files (discard changes) [High risk] - Loses current work

    Which should I choose?

YOU: "Commit first."

AI: Committing current changes...
    git add .
    git commit -m "Work in progress before checkpoint restore"

    Now restoring checkpoint "baseline"...
    βœ“ Restored checkpoint "baseline"

    Your previous work is safe in git history.

Checkpoint Management

Listing Checkpoints

See all checkpoints for a work unit:

fspec list-checkpoints AUTH-001

Output:

Checkpoints for AUTH-001:

πŸ“Œ  before-refactor (manual)
   Created: 2025-10-21T14:30:00.000Z

πŸ“Œ  baseline (manual)
   Created: 2025-10-21T13:15:00.000Z

πŸ€–  AUTH-001-auto-testing (automatic)
   Created: 2025-10-21T10:00:00.000Z

πŸ€–  AUTH-001-auto-specifying (automatic)
   Created: 2025-10-20T16:00:00.000Z

Visual indicators:

  • πŸ“Œ = Manual checkpoint (you created it)
  • πŸ€– = Automatic checkpoint (created by workflow)

Creating Checkpoints

fspec checkpoint AUTH-001 baseline
fspec checkpoint AUTH-001 before-refactor
fspec checkpoint AUTH-001 experiment-jwt

Naming guidelines:

  • Use descriptive names that explain WHY you're saving
  • βœ… Good: baseline, before-refactor, working-version
  • ❌ Bad: temp, test, checkpoint1

Restoring Checkpoints

fspec restore-checkpoint AUTH-001 baseline
fspec restore-checkpoint AUTH-001 before-refactor

Re-restorable: You can restore the same checkpoint multiple times for different experiments.

Cleaning Up Old Checkpoints

Keep last N checkpoints:

fspec cleanup-checkpoints AUTH-001 --keep-last 5

Output:

Cleaning up checkpoints for AUTH-001 (keeping last 5)...

Deleted 3 checkpoint(s):
  - experiment-1 (2025-10-20T10:00:00.000Z)
  - experiment-2 (2025-10-20T11:00:00.000Z)
  - old-baseline (2025-10-19T15:00:00.000Z)

Preserved 5 checkpoint(s):
  - current-state (2025-10-21T14:30:00.000Z)
  - working-version (2025-10-21T13:15:00.000Z)
  - baseline (2025-10-21T10:00:00.000Z)
  - AUTH-001-auto-testing (2025-10-21T09:00:00.000Z)
  - AUTH-001-auto-specifying (2025-10-20T16:00:00.000Z)

βœ“ Cleanup complete: 3 deleted, 5 preserved

Conflict Detection and Resolution

When you restore a checkpoint but your working directory has changed, fspec detects conflicts intelligently.

How Conflict Detection Works

Unlike git merge, fspec uses byte-level comparison to detect conflicts:

  1. Read current file: Get file contents from working directory
  2. Read checkpoint file: Get file contents from checkpoint
  3. Compare bytes: Exact byte-by-byte comparison
  4. List conflicts: Files that differ are conflicts

No merge markers: fspec doesn't insert <<<<<<<, =======, >>>>>>> markers. Instead, it gives AI full control over resolution.

AI-Assisted Conflict Resolution

When conflicts are detected, AI receives a system reminder:

<system-reminder>
CHECKPOINT RESTORATION CONFLICT DETECTED
 
The following 2 file(s) have been modified since checkpoint "baseline" was created:
  - src/auth/login.ts
  - src/auth/session.ts
 
Working directory changes will be LOST if you restore this checkpoint!
 
RECOMMENDED: Create new checkpoint first to preserve work:
  fspec checkpoint AUTH-001 before-restore
</system-reminder>

AI resolution steps:

  1. Read conflicted files using Read tool
  2. Understand what changed since checkpoint
  3. Create a new checkpoint to preserve current work (if valuable)
  4. Restore the original checkpoint
  5. Re-apply necessary changes from current work

Integration with Work Unit Workflow

Checkpoints integrate seamlessly with fspec's workflow states:

Automatic Checkpoint Triggers

Before each status transition (if working directory has changes):

specifying β†’ testing
  Creates: AUTH-001-auto-specifying

testing β†’ implementing
  Creates: AUTH-001-auto-testing

implementing β†’ validating
  Creates: AUTH-001-auto-implementing

validating β†’ done
  Creates: AUTH-001-auto-validating
  Then: Cleanup all auto-checkpoints (keep manual ones)

Why Cleanup Happens at Done

When work reaches "done", automatic checkpoints are no longer needed:

YOU: "Mark AUTH-001 as done."

AI: Moving AUTH-001 to done...
    βœ“ Work unit AUTH-001 moved to done

    🧹 Auto-cleanup: 3 auto-checkpoint(s) deleted:
       - AUTH-001-auto-specifying
       - AUTH-001-auto-testing
       - AUTH-001-auto-implementing

    Manual checkpoints preserved:
       - baseline (you might need this for reference)
       - working-version (for documentation)

Decision Flow: When to Use Checkpoints

Best Practices

βœ… DO

  • Create checkpoints before experiments - "Let me save this first..."
  • Use descriptive names - "baseline", "before-refactor", "working-jwt-impl"
  • Create baselines for comparisons - Save working state before trying alternatives
  • Clean up old checkpoints - Keep last 5-10 for each work unit
  • Trust automatic checkpoints - They're your safety net for workflow transitions
  • List checkpoints before restoring - Know what you're restoring to

❌ DON'T

  • Skip checkpoint creation - "I won't need it" (you will)
  • Use generic names - "temp", "test", "checkpoint1" (meaningless later)
  • Forget cleanup - Hundreds of checkpoints become unmanageable
  • Restore without checking - List checkpoints first to verify
  • Delete manual checkpoints rashly - They're permanent for a reason

Common Patterns

Pattern 1: A/B Testing Implementations

Create baseline, try A, restore, try B, keep winner:

πŸ“Œ Checkpoint "baseline" created
   ↓
Try Approach A β†’ Doesn't work
   ↓
βœ“ Restore "baseline"
   ↓
Try Approach B β†’ Works! βœ“
   ↓
Keep Approach B implementation

Pattern 2: Iterative Refactoring

Small, safe refactoring steps with checkpoints between each:

πŸ“Œ Checkpoint "before-refactor-step-1"
   ↓
Refactor step 1 (extract method)
   ↓
βœ“ Tests pass
   ↓
πŸ“Œ Checkpoint "before-refactor-step-2"
   ↓
Refactor step 2 (rename variables)
   ↓
βœ“ Tests pass
   ↓
Continue...

Pattern 3: Experimental Feature Development

Try radical new approach, keep fallback:

πŸ“Œ Checkpoint "working-version"
   ↓
Try experimental feature
   ↓
❌ Breaks too many things
   ↓
βœ“ Restore "working-version"
   ↓
Ship working version instead

Troubleshooting

Issue: Checkpoint creation fails

Error: No changes to checkpoint

Solution: Checkpoints require uncommitted changes. Make some changes first.

Issue: Restore fails with conflicts

Error: Conflicted files detected

Solution:

  1. Create a new checkpoint to save current work
  2. Then restore the original checkpoint
  3. Or force restore if you don't need current changes

Issue: Can't find checkpoint

Error: Checkpoint not found

Solution: List checkpoints to verify the name:

fspec list-checkpoints AUTH-001

Issue: Too many checkpoints

Problem: Hundreds of old checkpoints

Solution: Clean up periodically:

fspec cleanup-checkpoints AUTH-001 --keep-last 5

Summary

Git checkpoints transform how you experiment with code:

Before Checkpoints:

  • Fear of trying new approaches
  • Manual git operations
  • Lost work from failed experiments
  • Slow, careful changes

With Checkpoints:

  • βœ… Fearless experimentation
  • βœ… Instant rollback
  • βœ… Try multiple approaches safely
  • βœ… Automatic safety net
  • βœ… AI-driven development

Key Insight: Stop fearing mistakes. Start experimenting boldly.

Two Types:

  • πŸ€– Automatic: Created at workflow transitions, cleaned up at done
  • πŸ“Œ Manual: Created by you, kept forever

Core Commands:

fspec checkpoint <id> <name>           # Create
fspec list-checkpoints <id>            # List
fspec restore-checkpoint <id> <name>   # Restore
fspec cleanup-checkpoints <id> --keep-last N  # Clean up

Checkpoints are your time machine. Use them liberally.