import { buildMemberLaunchPresentation, getLaunchAwarePresenceLabel, getSpawnAwareDotClass, getSpawnAwarePresenceLabel, getSpawnCardClass, getMemberRuntimeAdvisoryLabel, getMemberRuntimeAdvisoryTitle, getMemberRuntimeAdvisoryTone, isOpenCodeRelaunchActionable, shouldDisplayMemberCurrentTask, } 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', providerId: 'gemini', removedAt: undefined, }; describe('memberHelpers spawn-aware presence', () => { it('does not display current task labels for offline or terminal launch states', () => { expect( shouldDisplayMemberCurrentTask({ member: { ...member, currentTaskId: 'task-1' }, isTeamAlive: false, }) ).toBe(false); expect( shouldDisplayMemberCurrentTask({ member: { ...member, currentTaskId: 'task-1' }, isTeamAlive: true, spawnStatus: 'offline', spawnLaunchState: 'confirmed_alive', spawnRuntimeAlive: false, }) ).toBe(false); expect( shouldDisplayMemberCurrentTask({ member: { ...member, currentTaskId: 'task-1' }, isTeamAlive: true, spawnStatus: 'error', spawnLaunchState: 'failed_to_start', }) ).toBe(false); }); it('does not display current task labels for runtime entries without a live agent runtime', () => { expect( shouldDisplayMemberCurrentTask({ member: { ...member, currentTaskId: 'task-1' }, isTeamAlive: true, spawnStatus: 'online', spawnLaunchState: 'confirmed_alive', runtimeEntry: { memberName: 'alice', alive: false, restartable: true, providerId: 'opencode', livenessKind: 'stale_metadata', updatedAt: '2026-04-24T12:00:00.000Z', }, }) ).toBe(false); }); it('keeps current task labels for confirmed online members', () => { expect( shouldDisplayMemberCurrentTask({ member: { ...member, currentTaskId: 'task-1' }, isTeamAlive: true, spawnStatus: 'online', spawnLaunchState: 'confirmed_alive', spawnRuntimeAlive: true, runtimeEntry: { memberName: 'alice', alive: true, restartable: true, providerId: 'gemini', livenessKind: 'confirmed_bootstrap', updatedAt: '2026-04-24T12:00:00.000Z', }, }) ).toBe(true); }); it('shows process-online teammates as online with a green dot', () => { expect( getSpawnAwarePresenceLabel( member, 'online', 'runtime_pending_bootstrap', 'process', true, false, true, false, undefined ) ).toBe('online'); expect( getSpawnAwareDotClass( member, 'online', 'runtime_pending_bootstrap', true, false, true, false, undefined ) ).toContain('bg-emerald-400'); expect( getSpawnAwareDotClass( member, 'online', 'runtime_pending_bootstrap', true, false, true, false, undefined ) ).toContain('animate-pulse'); }); it('keeps accepted-but-not-yet-online teammates in starting state', () => { expect( getSpawnAwarePresenceLabel( member, 'waiting', 'starting', undefined, false, false, true, false, undefined ) ).toBe('starting'); }); it('labels queued OpenCode lanes separately from active startup', () => { const openCodeMember: ResolvedTeamMember = { ...member, providerId: 'opencode' }; expect( buildMemberLaunchPresentation({ member: openCodeMember, spawnStatus: 'waiting', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeAdvisory: undefined, isLaunchSettling: true, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'queued', launchVisualState: 'queued', launchStatusLabel: 'queued', dotClass: expect.stringContaining('bg-zinc-400'), }); }); it('does not label non-OpenCode waiting lanes as queued', () => { expect( buildMemberLaunchPresentation({ member, spawnStatus: 'waiting', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeAdvisory: undefined, isLaunchSettling: true, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'starting', launchVisualState: 'waiting', launchStatusLabel: 'waiting to start', }); }); it('marks long-running starting states as stale without making them failed', () => { const presentation = buildMemberLaunchPresentation({ member, spawnStatus: 'waiting', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, spawnUpdatedAt: '2026-05-08T12:00:00.000Z', runtimeAdvisory: undefined, isLaunchSettling: true, isTeamAlive: true, isTeamProvisioning: false, nowMs: Date.parse('2026-05-08T12:03:00.000Z'), }); expect(presentation.presenceLabel).toBe('starting stale'); expect(presentation.launchVisualState).toBe('starting_stale'); expect(presentation.launchStatusLabel).toBe('starting stale'); expect(presentation.dotClass).toContain('bg-amber-400'); expect(presentation.dotClass).not.toContain('animate-pulse'); expect(presentation.cardClass).not.toContain('member-waiting-shimmer'); expect(presentation.spawnBadgeLabel).toBe('starting stale'); }); it('keeps OpenCode runtime evidence states more specific than queued', () => { const openCodeMember: ResolvedTeamMember = { ...member, providerId: 'opencode' }; expect( buildMemberLaunchPresentation({ member: openCodeMember, spawnStatus: 'waiting', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, providerId: 'opencode', livenessKind: 'registered_only', runtimeDiagnostic: 'registered runtime metadata without live process', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeAdvisory: undefined, isLaunchSettling: true, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'registered', launchVisualState: 'registered_only', launchStatusLabel: 'registered', }); }); it('keeps starting visuals after provisioning already transitioned out of active state', () => { expect( getSpawnAwarePresenceLabel( member, 'spawning', 'starting', undefined, false, false, true, false, undefined ) ).toBe('starting'); expect( getSpawnAwareDotClass(member, 'spawning', 'starting', false, false, true, false, undefined) ).toContain('bg-amber-400'); expect(getSpawnCardClass('spawning', 'starting', false, false)).toContain( 'member-waiting-shimmer' ); }); it('shows offline instead of stale starting visuals when the team is offline', () => { expect( getSpawnAwarePresenceLabel( member, 'spawning', 'starting', undefined, false, false, false, false, undefined ) ).toBe('offline'); expect( getSpawnAwareDotClass(member, 'spawning', 'starting', false, false, false, false, undefined) ).toContain('bg-red-400'); expect(getSpawnCardClass('spawning', 'starting', false, false, false, false)).toBe(''); }); it('keeps runtime-pending teammates in starting state while launch is still settling', () => { expect( getSpawnAwarePresenceLabel( member, 'online', 'runtime_pending_bootstrap', 'process', true, true, true, false, undefined ) ).toBe('starting'); expect( getSpawnAwareDotClass( member, 'online', 'runtime_pending_bootstrap', true, true, true, false, undefined ) ).toContain('bg-zinc-400'); expect( getSpawnCardClass('online', 'runtime_pending_bootstrap', true, true, true, false) ).toContain('member-waiting-shimmer'); }); it('shows confirmed teammates as ready instead of idle while launch is still settling', () => { expect( getSpawnAwarePresenceLabel( member, 'online', 'confirmed_alive', 'heartbeat', true, true, true, false, undefined ) ).toBe('ready'); }); it('derives runtime-pending and settling visual states from the same launch inputs', () => { const runtimePending = buildMemberLaunchPresentation({ member, spawnStatus: 'online', spawnLaunchState: 'runtime_pending_bootstrap', spawnLivenessSource: 'process', spawnRuntimeAlive: true, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }); const settling = buildMemberLaunchPresentation({ member, spawnStatus: 'online', spawnLaunchState: 'confirmed_alive', spawnLivenessSource: 'heartbeat', spawnRuntimeAlive: true, runtimeAdvisory: undefined, isLaunchSettling: true, isTeamAlive: true, isTeamProvisioning: false, }); expect(runtimePending.launchVisualState).toBe('runtime_pending'); expect(runtimePending.launchStatusLabel).toBe('waiting for bootstrap'); expect(settling.launchVisualState).toBe('settling'); expect(settling.launchStatusLabel).toBe('joining team'); }); it('surfaces permission-blocked teammates as awaiting permission instead of generic starting', () => { const permissionPending = buildMemberLaunchPresentation({ member, spawnStatus: 'online', spawnLaunchState: 'runtime_pending_permission', spawnLivenessSource: 'process', spawnRuntimeAlive: true, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }); expect(permissionPending.presenceLabel).toBe('awaiting permission'); expect(permissionPending.launchVisualState).toBe('permission_pending'); expect(permissionPending.launchStatusLabel).toBe('awaiting permission'); expect(permissionPending.dotClass).toContain('bg-amber-400'); expect(permissionPending.cardClass).toContain('member-waiting-shimmer'); }); it('surfaces bootstrap-stalled OpenCode teammates as actionable pending state', () => { const bootstrapStalled = buildMemberLaunchPresentation({ member: { ...member, providerId: 'opencode' }, spawnStatus: 'waiting', spawnLaunchState: 'runtime_pending_bootstrap', spawnLivenessSource: undefined, spawnRuntimeAlive: true, spawnBootstrapStalled: true, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }); expect(bootstrapStalled.presenceLabel).toBe('bootstrap stalled'); expect(bootstrapStalled.launchVisualState).toBe('bootstrap_stalled'); expect(bootstrapStalled.launchStatusLabel).toBe('bootstrap stalled'); expect(bootstrapStalled.dotClass).toContain('bg-amber-400'); }); it('surfaces strict runtime liveness diagnostics as launch labels', () => { expect( buildMemberLaunchPresentation({ member, spawnStatus: 'waiting', spawnLaunchState: 'runtime_pending_bootstrap', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, livenessKind: 'shell_only', pidSource: 'tmux_pane', runtimeDiagnostic: 'tmux pane foreground command is zsh', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'shell only', launchVisualState: 'shell_only', launchStatusLabel: 'shell only', }); expect( buildMemberLaunchPresentation({ member, spawnStatus: 'online', spawnLaunchState: 'runtime_pending_bootstrap', spawnLivenessSource: 'process', spawnRuntimeAlive: true, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, livenessKind: 'runtime_process_candidate', runtimeDiagnostic: 'OpenCode runtime process detected, but bootstrap is not confirmed', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'bootstrap unconfirmed', launchVisualState: 'runtime_candidate', launchStatusLabel: 'bootstrap unconfirmed', dotClass: expect.stringContaining('bg-amber-400'), }); expect( buildMemberLaunchPresentation({ member, spawnStatus: 'online', spawnLaunchState: 'confirmed_alive', spawnLivenessSource: 'process', spawnRuntimeAlive: true, spawnBootstrapConfirmed: true, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, livenessKind: 'registered_only', runtimeDiagnostic: 'registered runtime metadata without live process', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'online', launchVisualState: null, launchStatusLabel: null, dotClass: expect.stringContaining('bg-emerald-400'), }); expect( buildMemberLaunchPresentation({ member, spawnStatus: 'waiting', spawnLaunchState: 'confirmed_alive', spawnLivenessSource: 'process', spawnRuntimeAlive: true, spawnBootstrapConfirmed: true, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, livenessKind: 'registered_only', runtimeDiagnostic: 'registered runtime metadata without live process', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'online', launchVisualState: null, launchStatusLabel: null, dotClass: expect.stringContaining('bg-emerald-400'), }); }); it('marks stuck OpenCode launch states as manually relaunchable', () => { const openCodeMember: ResolvedTeamMember = { ...member, providerId: 'opencode' }; expect( isOpenCodeRelaunchActionable({ member: openCodeMember, spawnEntry: { status: 'online', launchState: 'confirmed_alive', runtimeAlive: false, bootstrapConfirmed: false, livenessKind: 'registered_only', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, providerId: 'opencode', livenessKind: 'registered_only', updatedAt: '2026-04-24T12:00:00.000Z', }, }) ).toBe(true); expect( isOpenCodeRelaunchActionable({ member: openCodeMember, spawnEntry: { status: 'online', launchState: 'runtime_pending_bootstrap', runtimeAlive: true, bootstrapConfirmed: false, livenessKind: 'runtime_process_candidate', firstSpawnAcceptedAt: '2026-04-24T12:00:00.000Z', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeEntry: { memberName: 'alice', alive: true, restartable: true, providerId: 'opencode', livenessKind: 'runtime_process_candidate', updatedAt: '2026-04-24T12:00:00.000Z', }, nowMs: Date.parse('2026-04-24T12:06:00.000Z'), }) ).toBe(true); }); it('does not mark fresh OpenCode runtime candidates as relaunchable', () => { expect( isOpenCodeRelaunchActionable({ member: { ...member, providerId: 'opencode' }, spawnEntry: { status: 'online', launchState: 'runtime_pending_bootstrap', runtimeAlive: true, bootstrapConfirmed: false, livenessKind: 'runtime_process_candidate', firstSpawnAcceptedAt: '2026-04-24T12:00:00.000Z', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeEntry: { memberName: 'alice', alive: true, restartable: true, providerId: 'opencode', livenessKind: 'runtime_process_candidate', updatedAt: '2026-04-24T12:00:00.000Z', }, nowMs: Date.parse('2026-04-24T12:01:00.000Z'), }) ).toBe(false); }); it('does not mark fresh OpenCode not-found checks as relaunchable', () => { expect( isOpenCodeRelaunchActionable({ member: { ...member, providerId: 'opencode' }, spawnEntry: { status: 'waiting', launchState: 'runtime_pending_bootstrap', runtimeAlive: false, bootstrapConfirmed: false, livenessKind: 'not_found', firstSpawnAcceptedAt: '2026-04-24T12:00:00.000Z', updatedAt: '2026-04-24T12:00:00.000Z', }, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, providerId: 'opencode', livenessKind: 'not_found', updatedAt: '2026-04-24T12:00:00.000Z', }, nowMs: Date.parse('2026-04-24T12:01:00.000Z'), }) ).toBe(false); expect( isOpenCodeRelaunchActionable({ member: { ...member, providerId: 'opencode' }, runtimeEntry: { memberName: 'alice', alive: false, restartable: true, providerId: 'opencode', livenessKind: 'not_found', updatedAt: '2026-04-24T12:00:00.000Z', }, nowMs: Date.parse('2026-04-24T12:01:00.000Z'), }) ).toBe(false); }); it('returns shared launch status labels without changing generic presence labels', () => { expect( buildMemberLaunchPresentation({ member, spawnStatus: 'waiting', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'starting', launchVisualState: 'waiting', launchStatusLabel: 'waiting to start', }); expect( buildMemberLaunchPresentation({ member, spawnStatus: 'spawning', spawnLaunchState: 'starting', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'starting', launchVisualState: 'spawning', launchStatusLabel: 'starting', }); expect( buildMemberLaunchPresentation({ member, spawnStatus: 'error', spawnLaunchState: 'failed_to_start', spawnLivenessSource: undefined, spawnRuntimeAlive: false, runtimeAdvisory: undefined, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }) ).toMatchObject({ presenceLabel: 'spawn failed', launchVisualState: 'error', launchStatusLabel: 'failed', }); }); it('renders unified retry advisory labels for provider retries', () => { expect( getMemberRuntimeAdvisoryLabel( { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2026-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'quota_exhausted', message: 'Gemini cli backend error: capacity exceeded.', }, 'gemini', Date.parse('2026-04-07T09:00:00.000Z') ) ).toBe('Gemini quota retry · 45s'); expect( getMemberRuntimeAdvisoryTitle( { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2026-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'rate_limited', message: 'Gemini cli backend error: rate limit 429.', }, 'gemini' ) ).toContain('Gemini rate limited the request'); }); it('keeps network advisories provider-neutral and appends raw details to the title', () => { expect( getMemberRuntimeAdvisoryLabel( { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2026-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'network_error', message: 'Connection timed out while contacting provider.', }, 'gemini', Date.parse('2026-04-07T09:00:00.000Z') ) ).toBe('Network retry · 45s'); expect( getMemberRuntimeAdvisoryTitle( { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2026-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'network_error', message: 'Connection timed out while contacting provider.', }, 'gemini' ) ).toContain('Connection timed out while contacting provider.'); }); it('renders local filesystem advisories as disk space errors', () => { const advisory = { kind: 'api_error' as const, observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'filesystem_error' as const, message: 'Local disk is full (ENOSPC). Free disk space and retry OpenCode delivery.', }; expect(getMemberRuntimeAdvisoryLabel(advisory, 'opencode')).toBe('Disk space error'); expect(getMemberRuntimeAdvisoryTitle(advisory, 'opencode')).toContain( 'Local disk is full or unavailable.' ); }); it('renders terminal API errors as errors instead of retrying status', () => { expect( getMemberRuntimeAdvisoryLabel( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'auth_error', statusCode: 500, message: 'API Error: 500 {"error":{"message":"auth_unavailable: no auth available"}}', }, 'anthropic', Date.parse('2026-04-07T09:00:00.000Z') ) ).toBe('Anthropic auth error'); expect( getMemberRuntimeAdvisoryTitle( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'auth_error', statusCode: 500, message: 'auth_unavailable: no auth available', }, 'anthropic' ) ).toContain('Anthropic authentication error'); }); it('renders timed OpenCode quota errors with retry/reset context', () => { const advisory = { kind: 'api_error' as const, observedAt: '2026-05-17T21:44:34.000Z', retryUntil: '2026-05-18T00:00:00.502Z', retryDelayMs: 8_126_502, reasonCode: 'quota_exhausted' as const, message: 'OpenCode session status retry - attempt=1 - Free usage exceeded, subscribe to Go https://opencode.ai/go - next=2026-05-18T00:00:00.502Z', }; expect( getMemberRuntimeAdvisoryLabel( advisory, 'opencode', Date.parse('2026-05-17T21:45:00.000Z') ) ).toBe('OpenCode quota error · retry 2h 15m'); const title = getMemberRuntimeAdvisoryTitle(advisory, 'opencode'); expect(title).toContain('OpenCode quota exhausted.'); expect(title).toContain('Waiting for OpenCode retry or quota reset around 00:00 UTC.'); expect(title).toContain('Free usage exceeded'); }); it('formats raw OpenCode protocol advisory reasons before showing them in titles', () => { const advisory = { kind: 'api_error' as const, observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'protocol_proof_missing' as const, message: 'visible_reply_still_required', }; expect(getMemberRuntimeAdvisoryLabel(advisory, 'opencode')).toBe('OpenCode proof missing'); expect(getMemberRuntimeAdvisoryTone(advisory)).toBe('warning'); const title = getMemberRuntimeAdvisoryTitle(advisory, 'opencode'); expect(title).toContain( 'OpenCode delivery completed without required visible/progress proof.' ); expect(title).toContain('OpenCode responded, but did not create a visible message_send reply.'); expect(title).not.toContain('visible_reply_still_required'); }); it('hides internal OpenCode bootstrap MCP diagnostics from advisory titles', () => { const title = getMemberRuntimeAdvisoryTitle( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'backend_error', message: 'OpenCode bootstrap MCP did not complete required tools before assistant response: runtime_bootstrap_checkin, member_briefing', }, 'opencode' ); expect(title).toContain('OpenCode runtime delivery did not complete.'); expect(title).not.toContain('runtime_bootstrap_checkin'); }); it('formats unknown OpenCode bridge outcome timeouts as delivery advisory text', () => { const advisory = { kind: 'api_error' as const, observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'backend_error' as const, message: 'opencode_prompt_acceptance_unknown_after_bridge_timeout', }; expect(getMemberRuntimeAdvisoryLabel(advisory, 'opencode')).toBe( 'OpenCode delivery error' ); const title = getMemberRuntimeAdvisoryTitle(advisory, 'opencode'); expect(title).toContain('OpenCode runtime delivery error.'); expect(title).toContain( 'OpenCode bridge outcome unknown after timeout, retrying/observing.' ); expect(title).not.toContain('Network or connectivity error'); expect(title).not.toContain('opencode_prompt_acceptance_unknown_after_bridge_timeout'); }); it('formats non-visible tool progress advisory reasons before showing them in titles', () => { const title = getMemberRuntimeAdvisoryTitle( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'protocol_proof_missing', message: 'non_visible_tool_without_task_progress', }, 'opencode' ); expect( getMemberRuntimeAdvisoryLabel( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'protocol_proof_missing', message: 'non_visible_tool_without_task_progress', }, 'opencode' ) ).toBe('OpenCode proof missing'); expect( getMemberRuntimeAdvisoryTone({ kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'protocol_proof_missing', message: 'non_visible_tool_without_task_progress', }) ).toBe('warning'); expect(title).toContain( 'OpenCode used tools, but did not create a visible reply or task progress proof.' ); expect(title).not.toContain('non_visible_tool_without_task_progress'); }); it('formats missing taskRefs advisory reasons before showing them in titles', () => { const title = getMemberRuntimeAdvisoryTitle( { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'protocol_proof_missing', message: 'visible_reply_missing_task_refs', }, 'opencode' ); expect(title).toContain( 'OpenCode created a reply without the required taskRefs metadata.' ); expect(title).not.toContain('visible_reply_missing_task_refs'); }); it('renders Codex native timeout separately from network errors', () => { const advisory = { kind: 'api_error' as const, observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'codex_native_timeout' as const, message: 'Codex native exec timed out after 120000ms.', }; expect(getMemberRuntimeAdvisoryLabel(advisory, 'codex')).toBe('Codex native timeout'); expect(getMemberRuntimeAdvisoryTitle(advisory, 'codex')).toContain( 'Codex native mailbox turn timed out' ); expect(getMemberRuntimeAdvisoryTitle(advisory, 'codex')).toContain( 'Codex native exec timed out after 120000ms.' ); }); it('marks launch presentation as an error when the runtime has a terminal API error', () => { const presentation = buildMemberLaunchPresentation({ member: { ...member, providerId: 'anthropic' }, spawnStatus: 'online', spawnLaunchState: 'runtime_pending_bootstrap', spawnLivenessSource: 'process', spawnRuntimeAlive: true, runtimeAdvisory: { kind: 'api_error', observedAt: '2026-04-07T09:00:00.000Z', reasonCode: 'auth_error', statusCode: 500, message: 'auth_unavailable: no auth available', }, isLaunchSettling: false, isTeamAlive: true, isTeamProvisioning: false, }); expect(presentation.presenceLabel).toBe('Anthropic auth error'); expect(presentation.runtimeAdvisoryTone).toBe('error'); expect(presentation.dotClass).toContain('bg-red-400'); }); it('falls back to the existing generic retry wording when no structured reason is present', () => { expect( getMemberRuntimeAdvisoryLabel( { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2026-04-07T09:00:45.000Z', retryDelayMs: 45_000, message: 'Gemini cli backend error: capacity exceeded.', }, 'gemini', Date.parse('2026-04-07T09:00:00.000Z') ) ).toBe('retrying now · 45s'); }); it('surfaces retry advisory text instead of plain online while bootstrap contact is still pending', () => { expect( getLaunchAwarePresenceLabel( member, 'online', 'runtime_pending_bootstrap', 'process', true, { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2099-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'quota_exhausted', message: 'Gemini cli backend error: capacity exceeded.', }, false, true, false, undefined ) ).toContain('Gemini quota retry'); expect( getLaunchAwarePresenceLabel( member, 'online', 'runtime_pending_bootstrap', 'process', false, { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2099-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'quota_exhausted', message: 'Gemini cli backend error: capacity exceeded.', }, false, true, false, undefined ) ).toBe('starting'); }); it('keeps retry advisory visible after contact when the teammate is otherwise just idle or ready', () => { expect( getLaunchAwarePresenceLabel( member, 'online', 'confirmed_alive', 'heartbeat', true, { kind: 'sdk_retrying', observedAt: '2026-04-07T09:00:00.000Z', retryUntil: '2099-04-07T09:00:45.000Z', retryDelayMs: 45_000, reasonCode: 'quota_exhausted', message: 'Gemini cli backend error: capacity exceeded.', }, false, true, false, undefined ) ).toContain('Gemini quota retry'); }); });