feat: Show resolving_conflict activity state on initiative cards

Add 'resolving_conflict' to InitiativeActivityState and detect active
conflict agents (name starts with conflict-) in deriveInitiativeActivity.
Conflict resolution takes priority over pending_review since the agent
is actively working.

- Add resolving_conflict to shared types and activity derivation
- Include conflict agents in listInitiatives agent filter (name + mode)
- Map resolving_conflict to urgent variant with pulse in InitiativeCard
- Add merge: prefix to INITIATIVE_LIST_RULES for merge event routing
- Add spawnConflictResolutionAgent to INVALIDATION_MAP
- Add getActiveConflictAgent to detail page agent: SSE invalidation
This commit is contained in:
Lukas May
2026-03-06 13:32:37 +01:00
parent 05efa9c08e
commit e3246baf51
8 changed files with 42 additions and 20 deletions

View File

@@ -32,11 +32,12 @@ export interface SerializedInitiative {
function activityVisual(state: string): { label: string; variant: StatusVariant; pulse: boolean } {
switch (state) {
case "executing": return { label: "Executing", variant: "active", pulse: true };
case "pending_review": return { label: "Pending Review", variant: "warning", pulse: true };
case "discussing": return { label: "Discussing", variant: "active", pulse: true };
case "detailing": return { label: "Detailing", variant: "active", pulse: true };
case "refining": return { label: "Refining", variant: "active", pulse: true };
case "executing": return { label: "Executing", variant: "active", pulse: true };
case "pending_review": return { label: "Pending Review", variant: "warning", pulse: true };
case "discussing": return { label: "Discussing", variant: "active", pulse: true };
case "detailing": return { label: "Detailing", variant: "active", pulse: true };
case "refining": return { label: "Refining", variant: "active", pulse: true };
case "resolving_conflict": return { label: "Resolving Conflict", variant: "urgent", pulse: true };
case "ready": return { label: "Ready", variant: "active", pulse: false };
case "blocked": return { label: "Blocked", variant: "error", pulse: false };
case "complete": return { label: "Complete", variant: "success", pulse: false };

View File

@@ -45,6 +45,10 @@ export function mapEntityStatus(rawStatus: string): StatusVariant {
case "medium":
return "warning";
// Urgent / conflict resolution
case "resolving_conflict":
return "urgent";
// Error / failed
case "crashed":
case "blocked":

View File

@@ -24,6 +24,7 @@ export const INITIATIVE_LIST_RULES: LiveUpdateRule[] = [
{ prefix: 'task:', invalidate: ['listInitiatives'] },
{ prefix: 'phase:', invalidate: ['listInitiatives'] },
{ prefix: 'agent:', invalidate: ['listInitiatives'] },
{ prefix: 'merge:', invalidate: ['listInitiatives'] },
];
export function useLiveUpdates(rules: LiveUpdateRule[]) {

View File

@@ -44,6 +44,7 @@ const INVALIDATION_MAP: Partial<Record<MutationName, QueryName[]>> = {
spawnArchitectDiscuss: ["listAgents"],
spawnArchitectPlan: ["listAgents"],
spawnArchitectDetail: ["listAgents", "listInitiativeTasks"],
spawnConflictResolutionAgent: ["listAgents", "listInitiatives", "getInitiative"],
// --- Initiatives ---
createInitiative: ["listInitiatives"],