Finalize turn-role invariants and legacy migration cutover
This commit is contained in:
103
src/paired-turn-identity.ts
Normal file
103
src/paired-turn-identity.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import type {
|
||||
PairedRoomRole,
|
||||
PairedTaskStatus,
|
||||
PairedTurnReservationIntentKind,
|
||||
} from './types.js';
|
||||
|
||||
export interface PairedTurnIdentity {
|
||||
turnId: string;
|
||||
taskId: string;
|
||||
taskUpdatedAt: string;
|
||||
intentKind: PairedTurnReservationIntentKind;
|
||||
role: PairedRoomRole;
|
||||
}
|
||||
|
||||
export function resolvePairedTurnRole(
|
||||
intentKind: PairedTurnReservationIntentKind,
|
||||
): PairedRoomRole {
|
||||
switch (intentKind) {
|
||||
case 'reviewer-turn':
|
||||
return 'reviewer';
|
||||
case 'arbiter-turn':
|
||||
return 'arbiter';
|
||||
case 'owner-turn':
|
||||
case 'owner-follow-up':
|
||||
case 'finalize-owner-turn':
|
||||
default:
|
||||
return 'owner';
|
||||
}
|
||||
}
|
||||
|
||||
export function buildPairedTurnId(args: {
|
||||
taskId: string;
|
||||
taskUpdatedAt: string;
|
||||
intentKind: PairedTurnReservationIntentKind;
|
||||
}): string {
|
||||
return [args.taskId, args.taskUpdatedAt, args.intentKind].join(':');
|
||||
}
|
||||
|
||||
export function buildPairedTurnIdentity(args: {
|
||||
taskId: string;
|
||||
taskUpdatedAt: string;
|
||||
intentKind: PairedTurnReservationIntentKind;
|
||||
role?: PairedRoomRole;
|
||||
turnId?: string | null;
|
||||
}): PairedTurnIdentity {
|
||||
const role = args.role ?? resolvePairedTurnRole(args.intentKind);
|
||||
if (role !== resolvePairedTurnRole(args.intentKind)) {
|
||||
throw new Error(
|
||||
`paired turn identity role mismatch: ${role} does not match ${args.intentKind}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
turnId:
|
||||
args.turnId ??
|
||||
buildPairedTurnId({
|
||||
taskId: args.taskId,
|
||||
taskUpdatedAt: args.taskUpdatedAt,
|
||||
intentKind: args.intentKind,
|
||||
}),
|
||||
taskId: args.taskId,
|
||||
taskUpdatedAt: args.taskUpdatedAt,
|
||||
intentKind: args.intentKind,
|
||||
role,
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveOwnerTurnIntentKind(args: {
|
||||
taskStatus?: PairedTaskStatus | null;
|
||||
hasHumanMessage?: boolean;
|
||||
}): 'owner-turn' | 'owner-follow-up' | 'finalize-owner-turn' {
|
||||
if (args.hasHumanMessage) {
|
||||
return 'owner-turn';
|
||||
}
|
||||
if (args.taskStatus === 'merge_ready') {
|
||||
return 'finalize-owner-turn';
|
||||
}
|
||||
return 'owner-follow-up';
|
||||
}
|
||||
|
||||
export function resolveRuntimePairedTurnIdentity(args: {
|
||||
taskId: string;
|
||||
taskUpdatedAt: string;
|
||||
role: PairedRoomRole;
|
||||
taskStatus?: PairedTaskStatus | null;
|
||||
hasHumanMessage?: boolean;
|
||||
}): PairedTurnIdentity {
|
||||
const intentKind =
|
||||
args.role === 'reviewer'
|
||||
? 'reviewer-turn'
|
||||
: args.role === 'arbiter'
|
||||
? 'arbiter-turn'
|
||||
: resolveOwnerTurnIntentKind({
|
||||
taskStatus: args.taskStatus,
|
||||
hasHumanMessage: args.hasHumanMessage,
|
||||
});
|
||||
return buildPairedTurnIdentity({
|
||||
taskId: args.taskId,
|
||||
taskUpdatedAt: args.taskUpdatedAt,
|
||||
intentKind,
|
||||
role: args.role,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user