fix: reconcile caller aggregates and strengthen evidence handling
This commit is contained in:
@@ -15,6 +15,7 @@ export interface AnalyticsLeg {
|
||||
event: AnalyticsEvent; first180At: number | null; first183At: number | null;
|
||||
acceptedAt: number | null; endedAt: number | null; finalCode: number;
|
||||
talkMs: number; durationAt: number; durationFinal: boolean; unknown: boolean;
|
||||
coverageGap?: boolean; durationAuthority?: number;
|
||||
}
|
||||
export interface AnalyticsCall { start: AnalyticsEvent; legs: Record<string, AnalyticsLeg>; }
|
||||
export interface AnalyticsCounts {
|
||||
@@ -67,26 +68,28 @@ export function foldAnalytics(call: AnalyticsCall | null, event: AnalyticsEvent)
|
||||
event, first180At: null, first183At: null, acceptedAt: null, endedAt: null,
|
||||
finalCode: 0, talkMs: 0, durationAt: 0, durationFinal: false, unknown: event.kind !== 'ATTEMPT'
|
||||
};
|
||||
if (event.kind === 'ATTEMPT') { leg.event = event; leg.unknown = false; }
|
||||
if (event.kind === 'ATTEMPT') { leg.event = event; if (!leg.coverageGap) leg.unknown = false; }
|
||||
if (event.kind === 'PROGRESS' && event.code === 180) leg.first180At = earliest(leg.first180At, event.at);
|
||||
if (event.kind === 'PROGRESS' && event.code === 183) leg.first183At = earliest(leg.first183At, event.at);
|
||||
if (event.kind === 'ACCEPTED' && event.code >= 200 && event.code < 300) leg.acceptedAt = earliest(leg.acceptedAt, event.at);
|
||||
if (event.kind === 'UNKNOWN') leg.unknown = true;
|
||||
if (event.kind === 'UNKNOWN') { leg.unknown = true; leg.coverageGap = true; }
|
||||
if (event.kind === 'END' || event.kind === 'RECONCILE') {
|
||||
if (leg.endedAt === null || event.at >= leg.endedAt) { leg.endedAt = event.at; leg.finalCode = event.code; }
|
||||
// END carries the producer's accumulated phase flags through separate replayable events.
|
||||
if (event.source === 'verified-dialog-final' || event.source === 'platform-final') leg.unknown = false;
|
||||
if (event.source === 'verified-dialog-final' && leg.acceptedAt !== null && event.talkMs === null) {
|
||||
leg.talkMs = Math.max(0, event.at - leg.acceptedAt); leg.durationAt = event.at; leg.durationFinal = true;
|
||||
if (event.source === 'platform-final' && !event.attemptId && !leg.coverageGap) leg.unknown = false;
|
||||
if (event.source === 'verified-dialog-final' && leg.acceptedAt !== null && event.talkMs === null && !leg.durationFinal) {
|
||||
leg.talkMs = Math.max(0, event.at - leg.acceptedAt); leg.durationAt = event.at; leg.durationFinal = true; leg.durationAuthority = 1;
|
||||
}
|
||||
}
|
||||
if (event.kind === 'ACCEPTED' && leg.endedAt !== null && !leg.durationFinal) {
|
||||
leg.talkMs = Math.max(0, leg.endedAt - event.at); leg.durationAt = leg.endedAt; leg.durationFinal = true;
|
||||
leg.talkMs = Math.max(0, leg.endedAt - event.at); leg.durationAt = leg.endedAt; leg.durationFinal = true; leg.durationAuthority = 1;
|
||||
}
|
||||
if (event.talkMs !== null && ['DURATION', 'END', 'RECONCILE'].includes(event.kind)) {
|
||||
const final = event.kind !== 'DURATION';
|
||||
if ((!leg.durationFinal || final) && event.at >= leg.durationAt) {
|
||||
leg.talkMs = event.talkMs; leg.durationAt = event.at; leg.durationFinal = final;
|
||||
const authority = event.kind === 'RECONCILE' ? 3 : final ? 2 : 0;
|
||||
const priorAuthority = leg.durationAuthority ?? (leg.durationFinal ? 1 : 0);
|
||||
if (authority > priorAuthority || (authority === priorAuthority && event.at >= leg.durationAt)) {
|
||||
leg.talkMs = event.talkMs; leg.durationAt = event.at; leg.durationFinal = final; leg.durationAuthority = authority;
|
||||
}
|
||||
}
|
||||
result.legs[key] = leg;
|
||||
|
||||
Reference in New Issue
Block a user