feat: Add merge conflict detection and agent resolution in initiative review
Pre-merge mergeability check via `git merge-tree --write-tree` (dry-run, no side effects). When conflicts exist the "Merge & Push" button is disabled and a ConflictResolutionPanel shows conflict files with options to resolve manually or spawn a conflict-resolution agent. Agent questions appear inline via QuestionForm; on completion the mergeability re-checks automatically. New server-side: MergeabilityResult type, BranchManager.checkMergeability, conflict-resolution prompt, checkInitiativeMergeability query, spawnConflictResolutionAgent mutation, getActiveConflictAgent query. New frontend: useConflictAgent hook, ConflictResolutionPanel component, mergeability badge + panel integration in InitiativeReview.
This commit is contained in:
74
apps/server/agent/prompts/conflict-resolution.ts
Normal file
74
apps/server/agent/prompts/conflict-resolution.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Conflict resolution prompt — spawned when initiative branch has merge conflicts
|
||||
* with the target branch.
|
||||
*/
|
||||
|
||||
import {
|
||||
SIGNAL_FORMAT,
|
||||
SESSION_STARTUP,
|
||||
GIT_WORKFLOW,
|
||||
CONTEXT_MANAGEMENT,
|
||||
} from './shared.js';
|
||||
|
||||
export function buildConflictResolutionPrompt(
|
||||
sourceBranch: string,
|
||||
targetBranch: string,
|
||||
conflicts: string[],
|
||||
): string {
|
||||
const conflictList = conflicts.map(f => `- \`${f}\``).join('\n');
|
||||
|
||||
return `<role>
|
||||
You are a Conflict Resolution agent. Your job is to merge \`${targetBranch}\` into \`${sourceBranch}\` and resolve all merge conflicts so the initiative branch is up to date with the target branch.
|
||||
</role>
|
||||
|
||||
<conflict_details>
|
||||
**Source branch (initiative):** \`${sourceBranch}\`
|
||||
**Target branch (default):** \`${targetBranch}\`
|
||||
|
||||
**Conflicting files:**
|
||||
${conflictList}
|
||||
</conflict_details>
|
||||
${SIGNAL_FORMAT}
|
||||
${SESSION_STARTUP}
|
||||
|
||||
<resolution_protocol>
|
||||
Follow these steps in order:
|
||||
|
||||
1. **Inspect divergence**: Run \`git log --oneline ${targetBranch}..${sourceBranch}\` and \`git log --oneline ${sourceBranch}..${targetBranch}\` to understand what each side changed.
|
||||
|
||||
2. **Review conflicting files**: For each conflicting file, read both versions:
|
||||
- \`git show ${sourceBranch}:<file>\`
|
||||
- \`git show ${targetBranch}:<file>\`
|
||||
|
||||
3. **Merge**: Run \`git merge ${targetBranch} --no-edit\`. This will produce conflict markers.
|
||||
|
||||
4. **Resolve each file**: For each conflicting file:
|
||||
- Read the file to see conflict markers (\`<<<<<<<\`, \`=======\`, \`>>>>>>>\`)
|
||||
- Understand both sides' intent from step 1-2
|
||||
- Choose the correct resolution — keep both changes when they don't overlap, prefer the more complete version when they do
|
||||
- If you genuinely cannot determine the correct resolution, signal "questions" explaining the ambiguity
|
||||
|
||||
5. **Verify**: Run \`git diff --check\` to confirm no conflict markers remain. Run the test suite to confirm nothing is broken.
|
||||
|
||||
6. **Commit**: Stage resolved files with \`git add <file>\` (never \`git add .\`), then \`git commit --no-edit\` to complete the merge commit.
|
||||
|
||||
7. **Signal done**: Write signal.json with status "done".
|
||||
</resolution_protocol>
|
||||
${GIT_WORKFLOW}
|
||||
${CONTEXT_MANAGEMENT}
|
||||
|
||||
<important>
|
||||
- You are merging ${targetBranch} INTO ${sourceBranch} — bringing the initiative branch up to date, NOT the other way around.
|
||||
- Do NOT force-push or rebase. A merge commit is the correct approach.
|
||||
- If tests fail after resolution, fix the code — don't skip tests.
|
||||
- If a conflict is genuinely ambiguous (e.g., both sides rewrote the same function differently), signal "questions" with the specific ambiguity and your proposed resolution.
|
||||
</important>`;
|
||||
}
|
||||
|
||||
export function buildConflictResolutionDescription(
|
||||
sourceBranch: string,
|
||||
targetBranch: string,
|
||||
conflicts: string[],
|
||||
): string {
|
||||
return `Resolve ${conflicts.length} merge conflict(s) between ${sourceBranch} and ${targetBranch}: ${conflicts.join(', ')}`;
|
||||
}
|
||||
@@ -15,3 +15,4 @@ export { buildChatPrompt } from './chat.js';
|
||||
export type { ChatHistoryEntry } from './chat.js';
|
||||
export { buildWorkspaceLayout } from './workspace.js';
|
||||
export { buildPreviewInstructions } from './preview.js';
|
||||
export { buildConflictResolutionPrompt, buildConflictResolutionDescription } from './conflict-resolution.js';
|
||||
|
||||
Reference in New Issue
Block a user