From 72517418d93784d8d47d4992d67311ca20ba5383 Mon Sep 17 00:00:00 2001 From: 777genius Date: Thu, 23 Apr 2026 01:59:59 +0300 Subject: [PATCH] fix(team): keep persisted launch members in spawn statuses --- .../services/team/TeamLaunchStateEvaluator.ts | 8 ++- .../team/TeamLaunchStateEvaluator.test.ts | 58 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 test/main/services/team/TeamLaunchStateEvaluator.test.ts diff --git a/src/main/services/team/TeamLaunchStateEvaluator.ts b/src/main/services/team/TeamLaunchStateEvaluator.ts index 245a8c9c..180821d3 100644 --- a/src/main/services/team/TeamLaunchStateEvaluator.ts +++ b/src/main/services/team/TeamLaunchStateEvaluator.ts @@ -484,7 +484,13 @@ export function snapshotToMemberSpawnStatuses( ): Record { if (!snapshot) return {}; const statuses: Record = {}; - for (const memberName of snapshot.expectedMembers) { + const memberNames = Array.from( + new Set([ + ...snapshot.expectedMembers.map(normalizeMemberName).filter(Boolean), + ...Object.keys(snapshot.members).map(normalizeMemberName).filter(Boolean), + ]) + ); + for (const memberName of memberNames) { const entry = snapshot.members[memberName]; if (!entry) continue; let status: MemberSpawnStatusEntry['status'] = 'offline'; diff --git a/test/main/services/team/TeamLaunchStateEvaluator.test.ts b/test/main/services/team/TeamLaunchStateEvaluator.test.ts new file mode 100644 index 00000000..5f5c5344 --- /dev/null +++ b/test/main/services/team/TeamLaunchStateEvaluator.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from 'vitest'; + +import { snapshotToMemberSpawnStatuses } from '../../../../src/main/services/team/TeamLaunchStateEvaluator'; + +describe('TeamLaunchStateEvaluator', () => { + it('keeps member spawn statuses for persisted members even when expectedMembers is stale', () => { + const statuses = snapshotToMemberSpawnStatuses({ + version: 1, + teamName: 'my-team', + runId: 'run-1', + leadSessionId: 'lead-session', + expectedMembers: ['alice'], + bootstrapExpectedMembers: ['alice'], + updatedAt: '2026-04-23T00:00:00.000Z', + launchPhase: 'active', + teamLaunchState: 'partial_pending', + summary: { + confirmedCount: 0, + pendingCount: 2, + failedCount: 0, + runtimeAlivePendingCount: 0, + }, + members: { + alice: { + launchState: 'runtime_pending_bootstrap', + diagnostics: ['waiting for teammate check-in'], + agentToolAccepted: true, + runtimeAlive: false, + bootstrapConfirmed: false, + hardFailure: false, + lastEvaluatedAt: '2026-04-23T00:00:00.000Z', + sources: {}, + }, + bob: { + launchState: 'runtime_pending_permission', + diagnostics: ['waiting for permission approval'], + agentToolAccepted: true, + runtimeAlive: true, + bootstrapConfirmed: false, + hardFailure: false, + pendingPermissionRequestIds: ['req-1'], + lastEvaluatedAt: '2026-04-23T00:00:01.000Z', + sources: {}, + }, + }, + } as any); + + expect(statuses.alice).toMatchObject({ + launchState: 'runtime_pending_bootstrap', + status: 'waiting', + }); + expect(statuses.bob).toMatchObject({ + launchState: 'runtime_pending_permission', + status: 'online', + pendingPermissionRequestIds: ['req-1'], + }); + }); +});