Merge pull request #93 from phj1081/codex/owner/ejclaw

Extract paired arbiter request helper
This commit is contained in:
Eyejoker
2026-04-29 10:38:55 +09:00
committed by GitHub
5 changed files with 80 additions and 76 deletions

View 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;

View File

@@ -9,9 +9,9 @@ import {
} from './db.js';
import { logger } from './logger.js';
import { markPairedTaskReviewReady } from './paired-workspace-manager.js';
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
import {
applyPairedTaskPatch,
requestArbiterOrEscalate,
transitionPairedTaskStatus,
} from './paired-execution-context-shared.js';
import { resolveOwnerCompletionSignal } from './paired-completion-signals.js';

View File

@@ -1,10 +1,8 @@
import { ARBITER_DEADLOCK_THRESHOLD } from './config.js';
import { getPairedWorkspace } from './db.js';
import { logger } from './logger.js';
import {
requestArbiterOrEscalate,
transitionPairedTaskStatus,
} from './paired-execution-context-shared.js';
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
import { transitionPairedTaskStatus } from './paired-execution-context-shared.js';
import {
resolveReviewerCompletionSignal,
resolveReviewerFailureSignal,

View File

@@ -1,8 +1,9 @@
import { isArbiterEnabled } from './config.js';
import { updatePairedTaskIfUnchanged } from './db.js';
import { logger } from './logger.js';
import type { PairedTaskStatus } from './types.js';
export { requestArbiterOrEscalate } from './paired-arbiter-request.js';
export type { RequestArbiterOrEscalateFn } from './paired-arbiter-request.js';
export {
resolveOwnerCompletionSignal,
resolveReviewerCompletionSignal,
@@ -152,74 +153,5 @@ export function applyPairedTaskPatch(args: {
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 ApplyPairedTaskPatchFn = typeof applyPairedTaskPatch;
export type RequestArbiterOrEscalateFn = typeof requestArbiterOrEscalate;

View File

@@ -48,9 +48,9 @@ import {
} from './paired-execution-context-reviewer.js';
import {
applyPairedTaskPatch,
requestArbiterOrEscalate,
transitionPairedTaskStatus,
} from './paired-execution-context-shared.js';
import { requestArbiterOrEscalate } from './paired-arbiter-request.js';
import { resolveCanonicalSourceRef } from './paired-source-ref.js';
import {
isOwnerWorkspaceRepairNeededError,