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:
@@ -9,6 +9,7 @@ export interface ActiveArchitectAgent {
|
||||
initiativeId: string;
|
||||
mode: string;
|
||||
status: string;
|
||||
name?: string;
|
||||
}
|
||||
|
||||
const MODE_TO_STATE: Record<string, InitiativeActivityState> = {
|
||||
@@ -30,6 +31,18 @@ export function deriveInitiativeActivity(
|
||||
if (initiative.status === 'archived') {
|
||||
return { ...base, state: 'archived' };
|
||||
}
|
||||
|
||||
// Check for active conflict resolution agent — takes priority over pending_review
|
||||
// because the agent is actively working to resolve merge conflicts
|
||||
const conflictAgent = activeArchitectAgents?.find(
|
||||
a => a.initiativeId === initiative.id
|
||||
&& a.name?.startsWith('conflict-')
|
||||
&& (a.status === 'running' || a.status === 'waiting_for_input'),
|
||||
);
|
||||
if (conflictAgent) {
|
||||
return { ...base, state: 'resolving_conflict' };
|
||||
}
|
||||
|
||||
if (initiative.status === 'pending_review') {
|
||||
return { ...base, state: 'pending_review' };
|
||||
}
|
||||
@@ -41,6 +54,7 @@ export function deriveInitiativeActivity(
|
||||
// so architect agents (discuss/plan/detail/refine) surface activity
|
||||
const activeAgent = activeArchitectAgents?.find(
|
||||
a => a.initiativeId === initiative.id
|
||||
&& !a.name?.startsWith('conflict-')
|
||||
&& (a.status === 'running' || a.status === 'waiting_for_input'),
|
||||
);
|
||||
if (activeAgent) {
|
||||
|
||||
@@ -129,16 +129,16 @@ export function initiativeProcedures(publicProcedure: ProcedureBuilder) {
|
||||
: await repo.findAll();
|
||||
}
|
||||
|
||||
// Fetch active architect agents once for all initiatives
|
||||
// Fetch active agents once for all initiatives (architect + conflict)
|
||||
const ARCHITECT_MODES = ['discuss', 'plan', 'detail', 'refine'];
|
||||
const allAgents = ctx.agentManager ? await ctx.agentManager.list() : [];
|
||||
const activeArchitectAgents = allAgents
|
||||
.filter(a =>
|
||||
ARCHITECT_MODES.includes(a.mode ?? '')
|
||||
(ARCHITECT_MODES.includes(a.mode ?? '') || a.name?.startsWith('conflict-'))
|
||||
&& (a.status === 'running' || a.status === 'waiting_for_input')
|
||||
&& !a.userDismissedAt,
|
||||
)
|
||||
.map(a => ({ initiativeId: a.initiativeId ?? '', mode: a.mode ?? '', status: a.status }));
|
||||
.map(a => ({ initiativeId: a.initiativeId ?? '', mode: a.mode ?? '', status: a.status, name: a.name }));
|
||||
|
||||
// Batch-fetch projects for all initiatives
|
||||
const projectRepo = ctx.projectRepository;
|
||||
|
||||
Reference in New Issue
Block a user