Recover Codex compaction failures in paired owner flow

This commit is contained in:
ejclaw
2026-04-15 03:11:14 +09:00
parent c76902a84b
commit 2ab3bddc0e
20 changed files with 449 additions and 18 deletions

View File

@@ -139,6 +139,7 @@ function buildPairedTask(overrides: Partial<PairedTask> = {}): PairedTask {
plan_notes: null,
review_requested_at: null,
round_trip_count: 0,
owner_failure_count: 0,
status: 'active',
arbiter_verdict: null,
arbiter_requested_at: null,
@@ -980,7 +981,7 @@ describe('paired execution context', () => {
);
});
it('still resets owner tasks to active after failed execution', () => {
it('increments owner failure count and resets owner tasks to active after failed execution', () => {
vi.mocked(db.getPairedTaskById).mockReturnValue(
buildPairedTask({
status: 'merge_ready',
@@ -998,11 +999,38 @@ describe('paired execution context', () => {
'task-1',
expect.objectContaining({
status: 'active',
owner_failure_count: 1,
updated_at: expect.any(String),
}),
);
});
it('requests arbiter after repeated owner execution failures without a visible verdict', () => {
vi.spyOn(config, 'isArbiterEnabled').mockReturnValue(true);
vi.mocked(db.getPairedTaskById).mockReturnValue(
buildPairedTask({
status: 'active',
owner_failure_count: 1,
}),
);
completePairedExecutionContext({
taskId: 'task-1',
role: 'owner',
status: 'failed',
summary: "Error running remote compact task: Unknown parameter: 'prompt_cache_retention'",
});
expect(db.updatePairedTask).toHaveBeenCalledWith(
'task-1',
expect.objectContaining({
status: 'arbiter_requested',
owner_failure_count: 2,
arbiter_requested_at: expect.any(String),
}),
);
});
it('releases the execution lease even when a completion handler throws', () => {
const transitionError = new Error('transition failed');
vi.mocked(db.getPairedTaskById).mockReturnValue(