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