fix(team): treat online teammates as ready state

This commit is contained in:
iliya 2026-04-07 12:29:21 +03:00
parent 340e4d8c8b
commit 8ebde439a8
4 changed files with 76 additions and 10 deletions

View file

@ -8995,8 +8995,12 @@ export class TeamProvisioningService {
const failedSpawnMembers = this.getFailedSpawnMembers(run);
const launchSummary = this.getMemberLaunchSummary(run);
const hasSpawnFailures = failedSpawnMembers.length > 0;
const stillStartingCount = Math.max(
0,
launchSummary.pendingCount - launchSummary.runtimeAlivePendingCount
);
const hasPendingBootstrap =
!hasSpawnFailures && launchSummary.pendingCount > 0 && run.expectedMembers.length > 0;
!hasSpawnFailures && stillStartingCount > 0 && run.expectedMembers.length > 0;
const readyMessage = hasSpawnFailures
? `Launch completed with teammate errors — ${failedSpawnMembers
.map((member) => member.name)
@ -9155,8 +9159,12 @@ export class TeamProvisioningService {
const failedSpawnMembers = this.getFailedSpawnMembers(run);
const launchSummary = this.getMemberLaunchSummary(run);
const hasSpawnFailures = failedSpawnMembers.length > 0;
const stillStartingCount = Math.max(
0,
launchSummary.pendingCount - launchSummary.runtimeAlivePendingCount
);
const hasPendingBootstrap =
!hasSpawnFailures && launchSummary.pendingCount > 0 && run.expectedMembers.length > 0;
!hasSpawnFailures && stillStartingCount > 0 && run.expectedMembers.length > 0;
const progress = updateProgress(
run,
'ready',

View file

@ -159,9 +159,7 @@ export const TeamProvisioningBanner = ({
? `Team provisioned — ${heartbeatConfirmedCount}/${fallbackTeammateCount} teammates made contact${processOnlyAliveCount > 0 ? `, ${processOnlyAliveCount} teammate${processOnlyAliveCount === 1 ? '' : 's'} online` : ''}${pendingSpawnCount > 0 ? `${processOnlyAliveCount > 0 ? ', ' : ', '}${pendingSpawnCount} still starting` : ''}`
: 'Team provisioned — teammates are still starting';
const readyDetailSeverity =
failedSpawnCount > 0 || processOnlyAliveCount > 0 || pendingSpawnCount > 0
? 'warning'
: undefined;
failedSpawnCount > 0 || pendingSpawnCount > 0 ? 'warning' : undefined;
const readyMessage =
failedSpawnCount > 0
? `Launch finished with errors — ${failedSpawnCount}/${Math.max(fallbackTeammateCount, failedSpawnCount)} teammates failed to start`
@ -191,9 +189,7 @@ export const TeamProvisioningBanner = ({
onCancel={null}
successMessage={readyMessage}
successMessageSeverity={
failedSpawnCount > 0 || processOnlyAliveCount > 0 || pendingSpawnCount > 0
? 'warning'
: 'success'
failedSpawnCount > 0 || pendingSpawnCount > 0 ? 'warning' : 'success'
}
onDismiss={() => setDismissed(true)}
/>

View file

@ -101,7 +101,7 @@ export const SPAWN_DOT_COLORS: Record<MemberSpawnStatus, string> = {
export const SPAWN_PRESENCE_LABELS: Record<MemberSpawnStatus, string> = {
offline: 'offline',
waiting: 'online',
waiting: 'starting',
spawning: 'starting',
online: 'ready',
error: 'spawn failed',
@ -123,7 +123,7 @@ export function getSpawnAwareDotClass(
return SPAWN_DOT_COLORS.error;
}
if (spawnLaunchState === 'runtime_pending_bootstrap' && spawnStatus === 'online') {
return SPAWN_DOT_COLORS.spawning;
return SPAWN_DOT_COLORS.online;
}
if (spawnStatus === 'waiting') {
return SPAWN_DOT_COLORS.waiting;

View file

@ -0,0 +1,62 @@
import {
getSpawnAwareDotClass,
getSpawnAwarePresenceLabel,
} from '@renderer/utils/memberHelpers';
import type { ResolvedTeamMember } from '@shared/types';
const member: ResolvedTeamMember = {
name: 'alice',
status: 'unknown',
taskCount: 0,
currentTaskId: null,
lastActiveAt: null,
messageCount: 0,
color: 'blue',
agentType: 'reviewer',
role: 'Reviewer',
removedAt: undefined,
};
describe('memberHelpers spawn-aware presence', () => {
it('shows process-online teammates as online with a green dot', () => {
expect(
getSpawnAwarePresenceLabel(
member,
'online',
'runtime_pending_bootstrap',
'process',
true,
true,
false,
undefined
)
).toBe('online');
expect(
getSpawnAwareDotClass(
member,
'online',
'runtime_pending_bootstrap',
true,
false,
undefined
)
).toContain('bg-emerald-400');
});
it('keeps accepted-but-not-yet-online teammates in starting state', () => {
expect(
getSpawnAwarePresenceLabel(
member,
'waiting',
'starting',
undefined,
false,
true,
true,
undefined
)
).toBe('starting');
});
});