diff --git a/src/paired-execution-context-shared.test.ts b/src/paired-execution-context-shared.test.ts index ed5befe..8f6bb59 100644 --- a/src/paired-execution-context-shared.test.ts +++ b/src/paired-execution-context-shared.test.ts @@ -166,6 +166,26 @@ describe('paired execution context shared verdict helpers', () => { ).toEqual({ kind: 'request_arbiter' }); }); + it('routes reviewer step_done to arbiter once round trips hit the deadlock threshold', () => { + // Below threshold: keep iterating with the owner. + expect( + resolveReviewerCompletionSignal({ + visibleVerdict: 'step_done', + roundTripCount: 1, + deadlockThreshold: 2, + }), + ).toEqual({ kind: 'request_owner_changes' }); + // At/above threshold: break the owner⇄reviewer step_done oscillation by + // escalating to the arbiter instead of looping forever. + expect( + resolveReviewerCompletionSignal({ + visibleVerdict: 'step_done', + roundTripCount: 2, + deadlockThreshold: 2, + }), + ).toEqual({ kind: 'request_arbiter' }); + }); + it('maps reviewer failure verdicts to explicit failure signals', () => { expect( resolveReviewerFailureSignal({ diff --git a/src/paired-execution-context-shared.ts b/src/paired-execution-context-shared.ts index b5b51ba..dcd995c 100644 --- a/src/paired-execution-context-shared.ts +++ b/src/paired-execution-context-shared.ts @@ -112,6 +112,9 @@ export function resolveReviewerCompletionSignal(args: { case 'done': return { kind: 'request_owner_finalize' }; case 'step_done': + if (roundTripCount >= deadlockThreshold) { + return { kind: 'request_arbiter' }; + } return { kind: 'request_owner_changes' }; case 'blocked': case 'needs_context':