fix(team): keep launch summary projection aligned
This commit is contained in:
parent
f036cf0386
commit
33f51b68a7
2 changed files with 56 additions and 3 deletions
|
|
@ -30,6 +30,10 @@ export interface PersistedTeamLaunchSummaryProjection extends LaunchStateSummary
|
|||
mixedAware?: true;
|
||||
}
|
||||
|
||||
function getPersistedLaunchMemberNames(snapshot: PersistedTeamLaunchSnapshot): string[] {
|
||||
return Array.from(new Set([...snapshot.expectedMembers, ...Object.keys(snapshot.members)]));
|
||||
}
|
||||
|
||||
function normalizeIsoDate(value: unknown): string | null {
|
||||
if (typeof value !== 'string') {
|
||||
return null;
|
||||
|
|
@ -48,7 +52,8 @@ function toMillis(value: string | undefined | null): number {
|
|||
export function createLaunchStateSummary(
|
||||
snapshot: PersistedTeamLaunchSnapshot
|
||||
): LaunchStateSummary {
|
||||
const missingMembers = snapshot.expectedMembers.filter((name) => {
|
||||
const persistedMemberNames = getPersistedLaunchMemberNames(snapshot);
|
||||
const missingMembers = persistedMemberNames.filter((name) => {
|
||||
const member = snapshot.members[name];
|
||||
return member?.launchState === 'failed_to_start';
|
||||
});
|
||||
|
|
@ -57,8 +62,8 @@ export function createLaunchStateSummary(
|
|||
...(snapshot.teamLaunchState === 'partial_failure'
|
||||
? { partialLaunchFailure: true as const }
|
||||
: {}),
|
||||
...(snapshot.expectedMembers.length > 0
|
||||
? { expectedMemberCount: snapshot.expectedMembers.length }
|
||||
...(persistedMemberNames.length > 0
|
||||
? { expectedMemberCount: persistedMemberNames.length }
|
||||
: {}),
|
||||
...(snapshot.summary.confirmedCount > 0
|
||||
? { confirmedMemberCount: snapshot.summary.confirmedCount }
|
||||
|
|
|
|||
|
|
@ -174,4 +174,52 @@ describe('TeamLaunchSummaryProjection', () => {
|
|||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('uses the union of expectedMembers and persisted members for summary projection', () => {
|
||||
const summary = createPersistedLaunchSummaryProjection({
|
||||
version: 2,
|
||||
teamName: 'mixed-team',
|
||||
updatedAt: '2026-04-22T12:00:00.000Z',
|
||||
launchPhase: 'finished',
|
||||
expectedMembers: ['alice'],
|
||||
members: {
|
||||
alice: {
|
||||
name: 'alice',
|
||||
providerId: 'codex',
|
||||
launchState: 'confirmed_alive',
|
||||
agentToolAccepted: true,
|
||||
runtimeAlive: true,
|
||||
bootstrapConfirmed: true,
|
||||
hardFailure: false,
|
||||
lastEvaluatedAt: '2026-04-22T12:00:00.000Z',
|
||||
},
|
||||
bob: {
|
||||
name: 'bob',
|
||||
providerId: 'opencode',
|
||||
launchState: 'failed_to_start',
|
||||
agentToolAccepted: true,
|
||||
runtimeAlive: false,
|
||||
bootstrapConfirmed: false,
|
||||
hardFailure: true,
|
||||
hardFailureReason: 'Side lane failed',
|
||||
lastEvaluatedAt: '2026-04-22T12:00:00.000Z',
|
||||
},
|
||||
},
|
||||
summary: {
|
||||
confirmedCount: 1,
|
||||
pendingCount: 0,
|
||||
failedCount: 1,
|
||||
runtimeAlivePendingCount: 0,
|
||||
},
|
||||
teamLaunchState: 'partial_failure',
|
||||
} as never);
|
||||
|
||||
expect(summary).toMatchObject({
|
||||
expectedMemberCount: 2,
|
||||
confirmedMemberCount: 1,
|
||||
missingMembers: ['bob'],
|
||||
failedCount: 1,
|
||||
teamLaunchState: 'partial_failure',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue