134 lines
5.2 KiB
Markdown
134 lines
5.2 KiB
Markdown
---
|
|
status: draft
|
|
system: integrations
|
|
requirements:
|
|
- REQ-INTEGRATIONS-GITHUB-PR-AUTO-FIX-CONFLICTS-001
|
|
created: 2026-09-05
|
|
owners:
|
|
- Kandev
|
|
---
|
|
# GitHub PR Auto-Fix Conflicts System Design
|
|
|
|
## Purpose and boundaries
|
|
|
|
The integration system owns GitHub mergeability state and auto-fix signal
|
|
classification. This design adds ordinary merge conflicts to the existing
|
|
per-PR auto-fix evaluator.
|
|
|
|
The design reuses the current poller, prompt renderer, session dispatcher,
|
|
round limit, and automation controls. Merge-queue removal behavior remains in
|
|
[GitHub PR Merge Queue Recovery](github-pr-merge-queue-recovery.md).
|
|
|
|
## Requirement mapping
|
|
|
|
| Requirement | Design section |
|
|
| --- | --- |
|
|
| `REQ-INTEGRATIONS-GITHUB-PR-AUTO-FIX-CONFLICTS-001` | [Conflict classification](#conflict-classification), [Checkpoint and prompt](#checkpoint-and-prompt), [Control help](#control-help) |
|
|
|
|
## Components and responsibilities
|
|
|
|
`TaskPR.MergeableState` carries the normalized GitHub mergeability state from
|
|
the latest lightweight pull-request sync.
|
|
|
|
`handleTaskPRCIAutoFix` in
|
|
`apps/backend/internal/orchestrator/event_handlers_github_ci_automation.go`
|
|
combines full feedback with pull-request state. It then builds the actionable
|
|
delta and current checkpoint.
|
|
|
|
The existing auto-fix dispatcher owns session selection, direct delivery,
|
|
durable queueing, coalescing, and round accounting. This change does not add a
|
|
second dispatch path.
|
|
|
|
## Conflict classification
|
|
|
|
The evaluator classifies only normalized `dirty` mergeability as an ordinary
|
|
merge conflict. It does not classify `blocked`, `behind`, `draft`, `unknown`,
|
|
or an empty state as a conflict.
|
|
|
|
The existing settled-check gate applies before conflict evaluation. This gate
|
|
keeps one auto-fix round focused on the final check, review, and conflict
|
|
snapshot.
|
|
|
|
## Checkpoint and prompt
|
|
|
|
`ciAutomationCheckpoint` adds an optional conflict item. The item contains:
|
|
|
|
- normalized mergeability state.
|
|
- head commit.
|
|
- head branch.
|
|
- base branch.
|
|
|
|
The JSON field is additive. Existing checkpoint rows decode with no conflict
|
|
item, so the change needs no database migration.
|
|
|
|
The current checkpoint contains one conflict item while the pull request is
|
|
`dirty`. The delta contains that item when no identical item exists in the
|
|
previous checkpoint.
|
|
|
|
An authoritative non-conflict observation removes the item during the existing
|
|
prompt-free checkpoint refresh. An empty or `unknown` state preserves the
|
|
prior item because GitHub can report these states during recomputation. A later
|
|
`dirty` observation is actionable after an authoritative clear. A changed head
|
|
commit or base branch also creates a new snapshot while the state remains
|
|
`dirty`.
|
|
|
|
When `{{pr.feedback}}` is present, `ciAutomationRenderSnapshot` adds a merge
|
|
conflict section. It names the sanitized head and base branches and the head
|
|
commit. The saved prompt remains hidden system context.
|
|
|
|
## Queue-removal compatibility
|
|
|
|
The same evaluator can include an ordinary conflict item and a queue-removal
|
|
item in one delta. The dispatcher sends one combined round for that evaluation.
|
|
|
|
For failed-check queue removals, current-head ownership requires both a
|
|
matching durable `last_queue_attempt_head_sha` and a non-empty
|
|
`last_merge_signature` written by an attempted or adopted queue entry. A
|
|
passive removal-only baseline does not prove which pull-request head produced
|
|
the removal, so it cannot start an auto-fix round. The removal event ID remains
|
|
the deduplication identity, and same-head automatic requeue protection remains
|
|
unchanged.
|
|
|
|
## Control help
|
|
|
|
`PRCIAutomationControls` keeps the existing switch label and responsive
|
|
surfaces. English and translated help state that auto-fix handles these inputs:
|
|
|
|
- settled failed checks.
|
|
- review comments.
|
|
- ordinary merge conflicts.
|
|
- actionable merge-queue removals.
|
|
|
|
The existing desktop popover and mobile drawer use the same localized copy.
|
|
No layout, navigation, touch target, or scroll behavior changes.
|
|
|
|
## Failure and recovery
|
|
|
|
- If mergeability is unknown, Kandev preserves prior conflict checkpoint state
|
|
and waits for a later authoritative state.
|
|
- If checks are unsettled, Kandev waits and does not use a round.
|
|
- If prompt delivery fails, the existing per-PR error and retry behavior apply.
|
|
- If a conflict clears, the checkpoint refresh is prompt-free.
|
|
- If Kandev restarts, the persisted JSON checkpoint preserves deduplication.
|
|
|
|
## Security
|
|
|
|
Branch names and commit identities are untrusted provider data. Snapshot
|
|
rendering uses the existing field sanitizer and `sysprompt.Wrap` boundary.
|
|
|
|
The change does not expand GitHub write permissions. The agent uses its current
|
|
task and repository permissions to repair the branch.
|
|
|
|
## Observability
|
|
|
|
Existing CI automation logs identify the task, repository, pull request, and
|
|
dispatch result. Focused tests cover conflict classification, checkpoint
|
|
transitions, queue-removal eligibility, and prompt rendering.
|
|
|
|
## Related decisions and designs
|
|
|
|
- [PR agent notifications](../../../decisions/0051-pr-agent-notifications-extend-task-pr-automation.md)
|
|
- [Bind automatic merge attempts to the reviewed head](../../../decisions/2026-08-28-bind-github-auto-merge-attempts-to-reviewed-head.md)
|
|
- [Task PR automation design](../../ui/system-design/ci-pr-automation-02.md)
|
|
- [GitHub PR Merge Queue Recovery](github-pr-merge-queue-recovery.md)
|