Extract paired arbiter request helper
This commit is contained in:
74
src/paired-arbiter-request.ts
Normal file
74
src/paired-arbiter-request.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { isArbiterEnabled } from './config.js';
|
||||||
|
import { logger } from './logger.js';
|
||||||
|
import { transitionPairedTaskStatus } from './paired-execution-context-shared.js';
|
||||||
|
import type { PairedTaskStatus } from './types.js';
|
||||||
|
|
||||||
|
export function requestArbiterOrEscalate(args: {
|
||||||
|
taskId: string;
|
||||||
|
currentStatus: PairedTaskStatus;
|
||||||
|
expectedUpdatedAt: string;
|
||||||
|
now: string;
|
||||||
|
arbiterLogMessage: string;
|
||||||
|
escalateLogMessage: string;
|
||||||
|
logContext?: Record<string, unknown>;
|
||||||
|
patch?: {
|
||||||
|
title?: string | null;
|
||||||
|
source_ref?: string | null;
|
||||||
|
plan_notes?: string | null;
|
||||||
|
review_requested_at?: string | null;
|
||||||
|
round_trip_count?: number;
|
||||||
|
owner_failure_count?: number;
|
||||||
|
owner_step_done_streak?: number;
|
||||||
|
finalize_step_done_count?: number;
|
||||||
|
task_done_then_user_reopen_count?: number;
|
||||||
|
empty_step_done_streak?: number;
|
||||||
|
arbiter_verdict?: string | null;
|
||||||
|
arbiter_requested_at?: string | null;
|
||||||
|
completion_reason?: string | null;
|
||||||
|
};
|
||||||
|
}): boolean {
|
||||||
|
const {
|
||||||
|
taskId,
|
||||||
|
currentStatus,
|
||||||
|
expectedUpdatedAt,
|
||||||
|
now,
|
||||||
|
arbiterLogMessage,
|
||||||
|
escalateLogMessage,
|
||||||
|
logContext,
|
||||||
|
} = args;
|
||||||
|
if (isArbiterEnabled()) {
|
||||||
|
const transitioned = transitionPairedTaskStatus({
|
||||||
|
taskId,
|
||||||
|
currentStatus,
|
||||||
|
nextStatus: 'arbiter_requested',
|
||||||
|
expectedUpdatedAt,
|
||||||
|
updatedAt: now,
|
||||||
|
patch: {
|
||||||
|
...args.patch,
|
||||||
|
arbiter_requested_at: now,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (transitioned) {
|
||||||
|
logger.info(logContext ?? { taskId }, arbiterLogMessage);
|
||||||
|
}
|
||||||
|
return transitioned;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transitioned = transitionPairedTaskStatus({
|
||||||
|
taskId,
|
||||||
|
currentStatus,
|
||||||
|
nextStatus: 'completed',
|
||||||
|
expectedUpdatedAt,
|
||||||
|
updatedAt: now,
|
||||||
|
patch: {
|
||||||
|
...args.patch,
|
||||||
|
completion_reason: 'escalated',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
if (transitioned) {
|
||||||
|
logger.info(logContext ?? { taskId }, escalateLogMessage);
|
||||||
|
}
|
||||||
|
return transitioned;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type RequestArbiterOrEscalateFn = typeof requestArbiterOrEscalate;
|
||||||
@@ -9,9 +9,9 @@ import {
|
|||||||
} from './db.js';
|
} from './db.js';
|
||||||
import { logger } from './logger.js';
|
import { logger } from './logger.js';
|
||||||
import { markPairedTaskReviewReady } from './paired-workspace-manager.js';
|
import { markPairedTaskReviewReady } from './paired-workspace-manager.js';
|
||||||
|
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
|
||||||
import {
|
import {
|
||||||
applyPairedTaskPatch,
|
applyPairedTaskPatch,
|
||||||
requestArbiterOrEscalate,
|
|
||||||
transitionPairedTaskStatus,
|
transitionPairedTaskStatus,
|
||||||
} from './paired-execution-context-shared.js';
|
} from './paired-execution-context-shared.js';
|
||||||
import { resolveOwnerCompletionSignal } from './paired-completion-signals.js';
|
import { resolveOwnerCompletionSignal } from './paired-completion-signals.js';
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import { ARBITER_DEADLOCK_THRESHOLD } from './config.js';
|
import { ARBITER_DEADLOCK_THRESHOLD } from './config.js';
|
||||||
import { getPairedWorkspace } from './db.js';
|
import { getPairedWorkspace } from './db.js';
|
||||||
import { logger } from './logger.js';
|
import { logger } from './logger.js';
|
||||||
import {
|
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
|
||||||
requestArbiterOrEscalate,
|
import { transitionPairedTaskStatus } from './paired-execution-context-shared.js';
|
||||||
transitionPairedTaskStatus,
|
|
||||||
} from './paired-execution-context-shared.js';
|
|
||||||
import {
|
import {
|
||||||
resolveReviewerCompletionSignal,
|
resolveReviewerCompletionSignal,
|
||||||
resolveReviewerFailureSignal,
|
resolveReviewerFailureSignal,
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { isArbiterEnabled } from './config.js';
|
|
||||||
import { updatePairedTaskIfUnchanged } from './db.js';
|
import { updatePairedTaskIfUnchanged } from './db.js';
|
||||||
import { logger } from './logger.js';
|
import { logger } from './logger.js';
|
||||||
import type { PairedTaskStatus } from './types.js';
|
import type { PairedTaskStatus } from './types.js';
|
||||||
|
|
||||||
|
export { requestArbiterOrEscalate } from './paired-arbiter-request.js';
|
||||||
|
export type { RequestArbiterOrEscalateFn } from './paired-arbiter-request.js';
|
||||||
export {
|
export {
|
||||||
resolveOwnerCompletionSignal,
|
resolveOwnerCompletionSignal,
|
||||||
resolveReviewerCompletionSignal,
|
resolveReviewerCompletionSignal,
|
||||||
@@ -152,74 +153,5 @@ export function applyPairedTaskPatch(args: {
|
|||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function requestArbiterOrEscalate(args: {
|
|
||||||
taskId: string;
|
|
||||||
currentStatus: PairedTaskStatus;
|
|
||||||
expectedUpdatedAt: string;
|
|
||||||
now: string;
|
|
||||||
arbiterLogMessage: string;
|
|
||||||
escalateLogMessage: string;
|
|
||||||
logContext?: Record<string, unknown>;
|
|
||||||
patch?: {
|
|
||||||
title?: string | null;
|
|
||||||
source_ref?: string | null;
|
|
||||||
plan_notes?: string | null;
|
|
||||||
review_requested_at?: string | null;
|
|
||||||
round_trip_count?: number;
|
|
||||||
owner_failure_count?: number;
|
|
||||||
owner_step_done_streak?: number;
|
|
||||||
finalize_step_done_count?: number;
|
|
||||||
task_done_then_user_reopen_count?: number;
|
|
||||||
empty_step_done_streak?: number;
|
|
||||||
arbiter_verdict?: string | null;
|
|
||||||
arbiter_requested_at?: string | null;
|
|
||||||
completion_reason?: string | null;
|
|
||||||
};
|
|
||||||
}): boolean {
|
|
||||||
const {
|
|
||||||
taskId,
|
|
||||||
currentStatus,
|
|
||||||
expectedUpdatedAt,
|
|
||||||
now,
|
|
||||||
arbiterLogMessage,
|
|
||||||
escalateLogMessage,
|
|
||||||
logContext,
|
|
||||||
} = args;
|
|
||||||
if (isArbiterEnabled()) {
|
|
||||||
const transitioned = transitionPairedTaskStatus({
|
|
||||||
taskId,
|
|
||||||
currentStatus,
|
|
||||||
nextStatus: 'arbiter_requested',
|
|
||||||
expectedUpdatedAt,
|
|
||||||
updatedAt: now,
|
|
||||||
patch: {
|
|
||||||
...args.patch,
|
|
||||||
arbiter_requested_at: now,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (transitioned) {
|
|
||||||
logger.info(logContext ?? { taskId }, arbiterLogMessage);
|
|
||||||
}
|
|
||||||
return transitioned;
|
|
||||||
}
|
|
||||||
|
|
||||||
const transitioned = transitionPairedTaskStatus({
|
|
||||||
taskId,
|
|
||||||
currentStatus,
|
|
||||||
nextStatus: 'completed',
|
|
||||||
expectedUpdatedAt,
|
|
||||||
updatedAt: now,
|
|
||||||
patch: {
|
|
||||||
...args.patch,
|
|
||||||
completion_reason: 'escalated',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (transitioned) {
|
|
||||||
logger.info(logContext ?? { taskId }, escalateLogMessage);
|
|
||||||
}
|
|
||||||
return transitioned;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TransitionPairedTaskStatusFn = typeof transitionPairedTaskStatus;
|
export type TransitionPairedTaskStatusFn = typeof transitionPairedTaskStatus;
|
||||||
export type ApplyPairedTaskPatchFn = typeof applyPairedTaskPatch;
|
export type ApplyPairedTaskPatchFn = typeof applyPairedTaskPatch;
|
||||||
export type RequestArbiterOrEscalateFn = typeof requestArbiterOrEscalate;
|
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ import {
|
|||||||
} from './paired-execution-context-reviewer.js';
|
} from './paired-execution-context-reviewer.js';
|
||||||
import {
|
import {
|
||||||
applyPairedTaskPatch,
|
applyPairedTaskPatch,
|
||||||
requestArbiterOrEscalate,
|
|
||||||
transitionPairedTaskStatus,
|
transitionPairedTaskStatus,
|
||||||
} from './paired-execution-context-shared.js';
|
} from './paired-execution-context-shared.js';
|
||||||
|
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
|
||||||
import { resolveCanonicalSourceRef } from './paired-source-ref.js';
|
import { resolveCanonicalSourceRef } from './paired-source-ref.js';
|
||||||
import {
|
import {
|
||||||
isOwnerWorkspaceRepairNeededError,
|
isOwnerWorkspaceRepairNeededError,
|
||||||
|
|||||||
Reference in New Issue
Block a user