feat(KB-010): add autoResolveConflicts setting with intelligent merge conflict resolution

- Add autoResolveConflicts setting to types and store (default: true)
- Implement smart conflict detection for lock files and generated files
- Add 3-attempt retry logic with escalating strategies to merger
- Auto-resolve lock files using 'ours', trivial whitespace conflicts
- Track mergeRetries per task for retry loop management
- Update AGENTS.md with conflict resolution documentation
- Add comprehensive merger tests for retry scenarios
This commit is contained in:
gsxdsm
2026-03-29 18:27:23 -07:00
parent 234f568e12
commit ddaf73554b
9 changed files with 1642 additions and 149 deletions

View File

@@ -345,6 +345,19 @@ describe("TaskStore", () => {
});
});
describe("autoResolveConflicts setting", () => {
it("persists autoResolveConflicts and returns it via getSettings", async () => {
await store.updateSettings({ autoResolveConflicts: false });
const settings = await store.getSettings();
expect(settings.autoResolveConflicts).toBe(false);
});
it("default settings have autoResolveConflicts set to true", async () => {
const settings = await store.getSettings();
expect(settings.autoResolveConflicts).toBe(true);
});
});
// ── Concurrent stress test ───────────────────────────────────────
describe("concurrent stress", () => {

View File

@@ -100,6 +100,8 @@ export interface Task {
log: TaskLogEntry[];
size?: "S" | "M" | "L";
reviewLevel?: number;
/** Number of merge retry attempts made for this task (auto-merge conflict recovery) */
mergeRetries?: number;
/** ISO-8601 timestamp of when the task last entered its current column.
* Used to sort cards within a column so that recently-moved cards appear at the top. */
columnMovedAt?: string;
@@ -177,6 +179,11 @@ export interface Settings {
* produce better results but cost more. When undefined, the engine
* uses the model's default thinking level. */
defaultThinkingLevel?: ThinkingLevel;
/** When true, auto-merge will automatically resolve common conflict patterns
* (lock files, generated files, trivial conflicts) without requiring AI
* intervention. When AI resolution fails, the system will retry with escalating
* strategies. Default: true. */
autoResolveConflicts?: boolean;
}
export const DEFAULT_SETTINGS: Settings = {
@@ -194,6 +201,7 @@ export const DEFAULT_SETTINGS: Settings = {
defaultProvider: undefined,
defaultModelId: undefined,
defaultThinkingLevel: undefined,
autoResolveConflicts: true,
};
export interface BoardConfig {
@@ -208,6 +216,10 @@ export interface MergeResult {
worktreeRemoved: boolean;
branchDeleted: boolean;
error?: string;
/** Strategy that successfully resolved the merge, if any */
resolutionStrategy?: "ai" | "auto-resolve" | "theirs";
/** Number of retry attempts made (1 = first attempt succeeded, 2-3 = retries needed) */
attemptsMade?: 1 | 2 | 3;
}
export const COLUMN_LABELS: Record<Column, string> = {