affectUI › Components › Agents

Conflict Radar

Agents working on their own branches at once, and where they get in each other's way – a row per file and a column per agent, a line between the agents that changed the same lines, each agent's way in one sentence to pick from, and Merge once all are settled.

Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/conflict-radar.json · Import from @/components/ui/conflict-radar

When to use

  • Several coding agents work on their own branches of the same repo at once, and people need to see where they overlap before anything is merged
  • Agents came up with different ways to solve the same thing and someone has to pick one

When not to use

  • When the agents try the same task and the best one simply wins – use Parallel Attempts
  • When the timeline matters – use Agent Lanes
  • For a single agent's changes – use Agent Ledger

Usage

import { ConflictRadar, type RadarAgent, type RadarFile } from "@/components/ui/conflict-radar";

export function Branches({ agents, files }: { agents: RadarAgent[]; files: RadarFile[] }) {
  const [resolved, setResolved] = useState<Record<string, string>>({});
  return (
    <ConflictRadar
      agents={agents} // { id, name, model?, avatar?, status?: "running" | "done" }
      files={files} // { path, edits: [{ agentId, lines: [from, to], summary?, active? }] }
      resolved={resolved}
      onResolve={(path, agentId) => setResolved((r) => ({ ...r, [path]: agentId }))}
      onMerge={() => mergeBranches(resolved)}
    />
  );
}

Props

NameTypeDefaultDescription
agentsRadarAgent[]One column each: name, model or branch, a mark, and whether it's still working
filesRadarFile[]One row each, with every agent's edit – the lines it changes, whether it's still writing, and for conflicts its way in one sentence
titlestring"Parallel work"Heading in the bar
resolvedRecord<string, string>The agent picked per conflicting file – leave it out and the component keeps the picks itself
onResolve(path: string, agentId: string) => voidA way was picked for a conflict
onMerge() => voidMerge was clicked – it's only enabled once every conflict is settled and every agent is done
classNamestringExtra class on the root

Keyboard

  • Tab: Moves through Merge, the conflicting files and the ways to settle the one in focus
  • Enter / Space: On a conflicting file: shows its ways below; on a way: keeps it

Accessibility

  • The grid is a table with the agents as column headers; every cell says who changed the file and whether it was kept
  • Conflicts and settled files are named in text, not only by color
  • The ways to settle a conflict are a radio group
  • The comparison is a polite live region, so the next conflict is announced when it comes into focus

Responsive

  • Below 440px agent names and folders drop, the columns get smaller and a way's sentence moves under its name
  • Dark mode built in; colors are CSS variables on .ui-cr

Requirements

  • React 19

Related

  • Parallel Attempts – An agent tries the same task several ways at once and the best one wins – every attempt races as a row with its model, approach and live bar, then gets a score; the best is marked and picked, and you can switch to another
  • Agent Lanes – Where every agent is right now – a live timeline with a lane per agent, tasks growing into “now”, hand-offs drawn between agents and approvals right on the block
  • Agent Ledger – Everything an agent changed in your systems, each change with an undo – before and after per row, and pointing at Undo shows what builds on it: what would be undone too, and what can't be taken back