Phase 2: Create Conflict Resolver Foundational Flow
## Overview
Create a foundational flow that autonomously resolves merge request conflicts — analyzing conflicted files, presenting a resolution plan, and (after user approval) editing files, committing, and pushing resolved changes.
## Key Behavior Change
⚠️ **This is NOT a guidance/advisory flow** — it **performs the actual conflict resolution**:
- Analyzes conflicts
- Determines resolution strategy
- **Asks user for approval**
- **Edits files to remove conflict markers**
- **Creates commit with resolved changes**
- **Pushes to source branch**
- Reports results to user
### Open question: Agent or Flow?
The original description proposed a foundational **chat agent**, but after investigating the codebase and [our glossary](https://docs.gitlab.com/ee/development/ai_features/glossary.md), a foundational **flow** appears to be the better fit:
| Criteria | Chat Agent | Flow | Conflict Resolver needs |
|----------|-----------|------|------------------------|
| Interaction | Conversational, open-ended | Triggered, structured sequence | Structured: analyze → plan → approve → execute |
| Execution | Advisory/generative | Autonomous with pre-approved privileges | Autonomous (edit files, commit, push) |
| Closest analog | Pipeline Builder (advises on CI config) | `developer/v1` (edits files, commits, creates MRs) | Same as `developer/v1` |
| Privileges | Defined per-tool in catalog | Explicit `pre_approved_agent_privileges` | Needs `READ_WRITE_FILES`, `USE_GIT`, `READ_WRITE_GITLAB` |
| Entry point | Duo Chat | Button/trigger/event | Button on MR page (per UX discussion on #588530) |
**Recommendation:** Follow the `developer/v1` pattern as a foundational flow. The UX can still surface this via a button that opens a progress view — flows don't require a chat interface.
If there are reasons to prefer a chat agent (e.g., the team wants iterative back-and-forth during resolution), we should discuss before implementation.
## Tasks
### 1. Register the foundational flow
Add entry to `ee/app/models/ai/catalog/foundational_flow.rb`:
```ruby
{
foundational_flow_reference: "resolve_merge_conflicts/v1",
display_name: s_("FoundationalFlow|Resolve Merge Conflicts"),
description: s_("FoundationalFlow|Automatically resolve merge request conflicts."),
feature_maturity: "experimental",
avatar: "gitlab-duo-flow.png",
pre_approved_agent_privileges: [
::Ai::DuoWorkflows::Workflow::AgentPrivileges::READ_WRITE_FILES,
::Ai::DuoWorkflows::Workflow::AgentPrivileges::READ_ONLY_GITLAB,
::Ai::DuoWorkflows::Workflow::AgentPrivileges::READ_WRITE_GITLAB,
::Ai::DuoWorkflows::Workflow::AgentPrivileges::USE_GIT,
::Ai::DuoWorkflows::Workflow::AgentPrivileges::RUN_MCP_TOOLS
],
environment: "web",
triggers: []
}
```
### 2. Create AI Catalog item + version
Create the flow definition in the AI Catalog with:
**Tools** (by actual ID from `built_in_tool_definitions.rb`):
| ID | Tool | Purpose |
|----|------|---------|
| 20 | `get_merge_request` | Fetch MR metadata (source/target branch, status) |
| 89 | `get_merge_request_conflicts` | Get raw conflict markers per file |
| 39 | `read_file` | Read full file content for context beyond conflict markers |
| 10 | `edit_file` | Apply conflict resolutions |
| 3 | `run_git_command` | Stage, commit, push resolved files |
| 1 | `gitlab_blob_search` | Search codebase for broader context when resolving |
| 24 | `grep` | Search for usages/patterns to inform resolution decisions |
| 9 | `create_merge_request_note` | Post resolution summary as MR comment |
### 3. System prompt requirements
The prompt MUST instruct the agent to:
**1. Analyze & Plan:**
- Fetch conflicts using `get_merge_request_conflicts`
- For each conflicted file, optionally use `read_file` to get broader context or `grep`/`gitlab_blob_search` to understand how conflicted code is used elsewhere
- Determine resolution strategy per file
- Assess confidence level per file
**2. Get User Approval:**
- Present clear resolution plan with per-file summary
- Explain what will be changed and why
- Show confidence level (high/medium/low)
- Flag files it can't confidently resolve (binary files, complex logic conflicts) for manual review
- **Wait for explicit approval** before executing
**3. Execute Autonomously:**
- Use `edit_file` to apply resolutions to each conflicting file
- Remove conflict markers (`<<<<<<<`, `=======`, `>>>>>>>`)
- Apply chosen resolution
- Stage changes
**4. Commit & Push:**
- Use `run_git_command` to create commit with descriptive message
- Push to source branch
- Handle errors gracefully (push failures, branch protection, etc.)
**5. Report Results:**
- Post summary via `create_merge_request_note`
- Confirm successful resolution with commit SHA
- If any issues occurred, report them and provide rollback guidance (e.g., `git revert <sha>`)
### 4. Feature flag
- Create `config/feature_flags/development/resolve_merge_conflicts_flow.yml`
- Gate the flow behind this flag (defaults to disabled)
### 5. Specs
- Flow registration in `foundational_flow.rb` (validate attributes, privileges)
- Feature flag gating
- Follow patterns from existing flow specs (e.g., `resolve_sast_vulnerability/v1`)
## What the MCP tool returns
For context — `get_merge_request_conflicts` (tool ID **89**, built in Phase 1) returns plain text:
```
# File: app/models/user.rb
<<<<<<< source_branch
def admin?
role == 'admin'
end
=======
def admin?
is_admin == true
end
>>>>>>> target_branch
```
No structured metadata, no line numbers, no conflict type classification. The agent needs to parse and reason about this raw output. Binary files and files over 200 KB are not supported.
## Expected flow
```
1. User clicks "Resolve with AI" on MR page
2. Flow is triggered → agent fetches conflict data
3. Agent analyzes 3 conflicted files:
- app/models/user.rb: Combine OAuth + 2FA methods (High confidence ✅)
- config/routes.rb: Keep both route sets (High confidence ✅)
- spec/models/user_spec.rb: Merge test suites (Medium confidence ⚠️)
4. Agent presents resolution plan → waits for user approval
5. User approves
6. Agent executes:
✅ Edited app/models/user.rb
✅ Edited config/routes.rb
✅ Edited spec/models/user_spec.rb
✅ Created commit abc1234
✅ Pushed to feature/oauth
7. Agent posts summary comment on MR
```
## Testing checklist
- [ ] Flow can be triggered and resolves simple text conflicts
- [ ] Agent **actually edits files** (not just suggests)
- [ ] Agent **creates commits** with descriptive messages
- [ ] Agent **pushes to branch** successfully
- [ ] Agent requests user approval before executing
- [ ] Agent handles push failures gracefully
- [ ] Agent respects branch protection rules
- [ ] Agent correctly flags unresolvable conflicts (binary, too complex)
- [ ] Error handling works (MR not found, no conflicts, permission denied)
## Safety considerations
- ✅ Get explicit user approval before executing
- ✅ Show what will be changed before execution
- ✅ Handle push failures gracefully
- ✅ Respect branch protection rules
- ✅ Never force push
- ✅ Provide rollback guidance if resolution was wrong
- ✅ Log all actions for audit trail
## Acceptance criteria
- [ ] Flow registered in `foundational_flow.rb` with correct privileges
- [ ] AI Catalog item created with system prompt and tool configuration
- [ ] System prompt emphasizes **autonomous execution with approval**
- [ ] Feature flag created and defaults to disabled
- [ ] Flow successfully resolves simple text conflicts end-to-end
- [ ] Specs pass
## Errata from original description
The original description (LLM-generated) had several inaccuracies:
- Said to register as foundational chat agent in `foundational_chat_agents_definitions.rb` — execution pattern matches a foundational flow instead
- Said agent ID 5, but that's already `pipeline_builder`
- Said tool ID 88 for `get_merge_request_conflicts` — actual ID is **89** (88 is `run_glql_query`)
Related to &20688
issue