retcon 1.1.0

Turn messy development commits into clean, logical history. Because you knew what you were doing the whole time.
Documentation
# The Reconstruction Loop

Retcon reconstructs clean history through a deterministic loop with LLM-powered steps.

## Algorithm

```
1. Load history spec from TOML
2. Create cleaned branch from merge-base(source, remote) if needed
3. Find first commit where history doesn't end in "complete"
4. For each remaining commit:
   a. Compute diff: cleaned..source
   b. LLM: Extract relevant changes for this commit from diff
   c. LLM: Apply changes and create commit
   d. Append CommitCreated { hash } to history, save TOML
   e. Loop:
      - Run build and tests
      - If pass: append Complete to history, save TOML, next commit
      - If fail:
        - Compute diff: cleaned..source
        - LLM: Assess - can you make progress?
          - If yes: fix, create WIP commit, append CommitCreated, save TOML
          - If no: append Stuck { summary }, save TOML, stop
5. Report results
```

## Deterministic vs LLM Boundaries

Following the patchwork philosophy ("do things deterministically that are deterministic"):

| Deterministic (Rust) | LLM-powered |
|---------------------|-------------|
| Parse TOML spec | Extract relevant diff hunks |
| Create/checkout branches | Decide what changes belong together |
| Compute diffs | Apply changes to files |
| Run build/test commands | Write commit messages |
| Track loop state | Diagnose build failures |
| | Determine what else to pull from source |

## The Fix Loop

When a commit doesn't build or tests fail, retcon enters a fix loop:

```
┌─────────────────────────────────────────────────────────┐
│                     Fix Loop                            │
│                                                         │
│  ┌──────────┐    ┌───────────┐    ┌──────────────────┐ │
│  │ Run      │───▶│ Pass?     │─Y─▶│ Append Complete  │ │
│  │ build    │    └───────────┘    │ Next commit      │ │
│  └──────────┘          │N         └──────────────────┘ │
│       ▲                ▼                               │
│       │         ┌───────────┐                          │
│       │         │ Compute   │                          │
│       │         │ new diff  │                          │
│       │         └───────────┘                          │
│       │                │                               │
│       │                ▼                               │
│       │         ┌─────────────────┐                    │
│       │         │ LLM: Can you    │                    │
│       │         │ make progress?  │                    │
│       │         └─────────────────┘                    │
│       │           │Y          │N                       │
│       │           ▼           ▼                        │
│       │    ┌──────────┐  ┌──────────────┐              │
│       │    │ Fix +    │  │ Append Stuck │              │
│       │    │ WIP      │  │ Stop         │              │
│       │    │ commit   │  └──────────────┘              │
│       │    └──────────┘                                │
│       │           │                                    │
│       │           ▼                                    │
│       │    ┌──────────────────┐                        │
│       │    │ Append           │                        │
│       │    │ CommitCreated    │                        │
│       │    │ Save TOML        │                        │
│       │    └──────────────────┘                        │
│       │           │                                    │
│       └───────────┘                                    │
└─────────────────────────────────────────────────────────┘
```

Key insight: each iteration recomputes the diff from cleaned to source. This means the LLM can pull in additional changes that it now realizes are needed - perhaps a helper function, a type definition, or an import that the original extraction missed.

### LLM Progress Assessment

Instead of a fixed iteration limit, the LLM assesses after each failed build:

> "Given the build errors and the remaining diff from source, can you make progress? Or are you stuck?"

The LLM returns one of:
- **Progress**: "I can fix this" → creates WIP commit, loop continues
- **Stuck**: "I need help: <summary>" → appends `Stuck`, stops

This lets the LLM recognize situations it can't resolve:
- Circular dependencies between commits
- Missing context it can't infer
- Ambiguous hints that need clarification
- Changes that don't belong together

### WIP Commits

Fix iterations create commits prefixed with `WIP:`:

```
feat: add OAuth provider authentication
WIP: add missing TokenRefresh import
WIP: include refresh_token helper that was needed
```

This creates an honest record of what happened. The history tracks every commit:

```toml
history = [
    { commit_created = "a1b2c3d" },  # initial attempt
    { commit_created = "e4f5g6h" },  # WIP: add missing import
    { commit_created = "i7j8k9l" },  # WIP: include helper
    "complete",
]
```

Options for handling WIP commits:
- **Keep them**: Transparent history of the reconstruction
- **Squash manually**: `git rebase -i` to fold WIPs into their parent
- **Future**: `--squash-wip` flag to auto-collapse

### Resuming After Stuck

When retcon encounters a `Stuck` entry, it requires explicit human resolution before continuing:

1. **Stuck**: retcon stops and shows the summary
2. **Intervene**: Edit hints, reorder commits, make manual fixes
3. **Resolve**: Add a `resolved` entry to the history describing what you changed:
   ```toml
   { resolved = "Reordered commits to resolve circular dependency" }
   ```
4. **Resume**: Run retcon again - it passes your resolution note to the LLM as context

If you try to resume without adding a `resolved` entry, retcon will stop immediately and remind you to add one. This ensures the LLM gets context about what changed.

The TOML file is the complete state - you can edit it, inspect the history, and resume at any point.

## Tools Provided to LLM

During reconstruction, the LLM has access to:

| Tool | Purpose |
|------|---------|
| `read_file` | Read file contents from working tree |
| `write_file` | Write file contents |
| `read_diff` | Get the current cleaned..source diff |
| `run_build` | Execute build command, get output |
| `run_tests` | Execute test command, get output |
| `create_commit` | Stage all changes and commit with message |

The LLM does NOT have:
- Direct git access (retcon manages branches)
- Network access
- Ability to modify the source branch

## Example Session

```
$ retcon reconstruct history-spec.toml

Loading spec: history-spec.toml
  Source: feature-oauth
  Remote: origin/main
  Cleaned: feature-oauth-clean

Creating cleaned branch from merge-base...
  Base commit: a1b2c3d

Commit 1/4: refactor: extract validation logic
  Computing diff (847 lines)...
  Extracting relevant changes...
  Creating commit...
  Building... PASS
  Tests... PASS
  ✓ Commit created

Commit 2/4: feat: add OAuth configuration
  Computing diff (623 lines)...
  Extracting relevant changes...
  Creating commit...
  Building... FAIL (missing import)
  Fix attempt 1:
    Consulting diff for missing pieces...
    Adding TokenConfig import...
    Creating WIP commit...
  Building... PASS
  Tests... PASS
  ✓ Commit created (1 WIP)

Commit 3/4: feat: implement OAuth flow
  Computing diff (412 lines)...
  ...

Complete!
  4 logical commits created
  2 WIP fix commits
  Branch: feature-oauth-clean

To squash WIP commits:
  git checkout feature-oauth-clean
  git rebase -i HEAD~6
```

### Example: Stuck and Resume

```
$ retcon execute history-spec.toml

...
Commit 3/4: feat: implement OAuth flow
  Computing diff (412 lines)...
  Extracting relevant changes...
  Creating commit...
  Building... FAIL (undefined type TokenStore)

  Assessing progress...
  Fix attempt 1:
    Adding TokenStore from diff...
    Creating WIP commit...
  Building... FAIL (TokenStore needs SessionManager)

  Assessing progress...
  LLM: "I'm stuck. TokenStore depends on SessionManager which depends on
        TokenStore - circular dependency. The commits may need reordering,
        or these changes need to be in the same commit."

  ✗ Stuck - stopping

$ # Try to resume without resolving...
$ retcon execute history-spec.toml

Resuming from commit 3/4: feat: implement OAuth flow
  ✗ Previously stuck - add a `resolved` entry to continue
    Edit the spec file and add after the `stuck` entry:
    { resolved = "description of what you changed" }

$ # User edits spec - combines commits 3 and 4
$ vim history-spec.toml
# Add: { resolved = "Combined OAuth flow and SessionManager into one commit" }

$ retcon execute history-spec.toml

Resuming from commit 3/4: feat: implement OAuth flow
  Resolved: Combined OAuth flow and SessionManager into one commit
  Computing diff...
  ...
```