Implement Interactive Merge Tool Integration
Implement interactive merge tool (vimdiff/mergetool) support for manual conflict resolution.
## Overview
When auto-resolution fails (git merge-file produces conflict markers), provide an optional interactive mode that launches the user's preferred merge tool.
**Note**: This is an enhancement on top of the basic manual workflow. Users can always:
1. Edit the issue file directly
2. Run `conflicts resolve <IID>` (works offline thanks to cached remote)
This feature adds the option to launch vimdiff/mergetool for a more guided experience.
## Prerequisite: Remote Version Storage (#170)
For offline operation, #170 must store the remote version when conflict is detected:
- Store in `.issues/.sync/conflicts/<iid>_remote.md`
- Clean up when conflict resolved
**Benefits**:
- `conflicts resolve <IID>` works offline (#168)
- `conflicts resolve <IID> --interactive` works offline (this issue)
## When This Is Used
```
Conflict detected during push
↓
Remote version cached in .issues/.sync/conflicts/<iid>_remote.md
↓
User runs: gl-issue-sync conflicts resolve 42 --interactive
↓
Launch vimdiff/mergetool with three-way view (offline)
↓
User resolves in tool, saves, exits
↓
Update local file + original (from cache) + clear conflict + delete cache
```
## Requirements
- [ ] Add `--interactive` / `-i` flag to `conflicts resolve`
- [ ] Load cached remote from `.issues/.sync/conflicts/<iid>_remote.md`
- [ ] Detect user's merge tool (`git config merge.tool`)
- [ ] Fall back to vimdiff if not configured
- [ ] Create temp files for three-way merge
- [ ] Launch merge tool and wait for completion
- [ ] On success: update local, update original from cache, clear conflict, delete cache
- [ ] On abort: leave everything unchanged
## Merge Tool Detection
```python
def get_merge_tool() -> str:
"""Get user's preferred merge tool or default to vimdiff."""
result = subprocess.run(["git", "config", "merge.tool"], capture_output=True, text=True)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()
return "vimdiff"
```
## Interactive Resolution Flow
```python
def resolve_interactive(iid):
# 1. Load local, original, cached remote (all offline)
local = load_issue(iid)
original = load_original_snapshot(iid)
remote = load_cached_remote(iid)
if remote is None:
error("Remote version not cached. Re-run 'push' to detect conflict.")
return
# 2. Create temp files for description
with tempfile.TemporaryDirectory() as tmpdir:
local_path = write_temp(tmpdir, "LOCAL", local.description)
original_path = write_temp(tmpdir, "BASE", original.description)
remote_path = write_temp(tmpdir, "REMOTE", remote.description)
merged_path = write_temp(tmpdir, "MERGED", local.description)
# 3. Launch merge tool
tool = get_merge_tool()
cmd = build_mergetool_cmd(tool, local_path, original_path, remote_path, merged_path)
result = subprocess.run(cmd)
if result.returncode != 0:
print("Merge aborted")
return
# 4. Update local issue with merged content
local.description = read_file(merged_path)
save_issue(local)
# 5. Update original to cached remote (from #168's shared logic)
save_original_snapshot(remote)
# 6. Clear conflict
clear_conflict(iid) # Removes from conflicts.json + deletes cache
print(f"✓ Issue #{iid} resolved")
print("Run 'gl-issue-sync push' to sync your changes")
```
## Example Usage
```
$ gl-issue-sync conflicts resolve 42 --interactive
Launching vimdiff for three-way merge...
[vimdiff opens with LOCAL | BASE | REMOTE | MERGED]
[User resolves, saves, exits]
✓ Issue #42 resolved
Run 'gl-issue-sync push' to sync your changes
```
## Supported Merge Tools
- vimdiff (default)
- meld
- kdiff3
- opendiff
- p4merge
- Any tool configured in `git config merge.tool`
## Acceptance Criteria
- [ ] `--interactive` / `-i` flag added to `conflicts resolve`
- [ ] Uses cached remote (fully offline)
- [ ] Detects user's `git config merge.tool`
- [ ] Falls back to vimdiff
- [ ] Three-way merge view works correctly
- [ ] Success: updates local + original + clears conflict
- [ ] Abort: leaves everything unchanged
- [ ] Works with common merge tools
task