feat: implement MAGI 3-agent arbiter system for deadlock resolution
Introduces a third agent role (arbiter) that is summoned on-demand when owner and reviewer reach a deadlock (same verdict 3+ rounds). Architecture: - 3 Discord bots: owner (codex), reviewer (claude), arbiter (claude/codex) - Arbiter is NOT always-on — only invoked when deadlock detected - Arbiter renders binding verdict: PROCEED/REVISE/RESET/ESCALATE - Non-escalate verdicts reset round_trip_count and resume ping-pong - Backward compatible: ARBITER_AGENT_TYPE unset = existing 2-agent mode Changes across 13 source files + 7 test files: - types.ts: PairedRoomRole += 'arbiter', new statuses, ArbiterVerdict type - config.ts: ARBITER_AGENT_TYPE, ARBITER_SERVICE_ID, ARBITER_DEADLOCK_THRESHOLD - db.ts: schema migration (arbiter columns in channel_owner + paired_tasks) - service-routing.ts: arbiter_service_id in lease - room-role-context.ts: arbiter role detection - paired-execution-context.ts: deadlock->arbiter, verdict handling - message-runtime.ts: arbiter turn routing, cursor, sender labeling - message-agent-executor.ts: arbiter mode, failover - agent-runner.ts + environment.ts: arbiter container mode - platform-prompts.ts: arbiter prompt loading New files: - prompts/arbiter-paired-room.md: arbiter system prompt - src/arbiter-context.ts: builds conversation context for arbiter judgment
This commit is contained in:
@@ -10,6 +10,7 @@ describe('buildRoomRoleContext', () => {
|
||||
chat_jid: 'group@test',
|
||||
owner_service_id: 'claude',
|
||||
reviewer_service_id: 'codex-main',
|
||||
arbiter_service_id: null,
|
||||
activated_at: null,
|
||||
reason: null,
|
||||
explicit: false,
|
||||
@@ -22,6 +23,7 @@ describe('buildRoomRoleContext', () => {
|
||||
ownerServiceId: 'claude',
|
||||
reviewerServiceId: 'codex-main',
|
||||
failoverOwner: false,
|
||||
arbiterServiceId: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,6 +34,7 @@ describe('buildRoomRoleContext', () => {
|
||||
chat_jid: 'group@test',
|
||||
owner_service_id: 'codex-review',
|
||||
reviewer_service_id: 'codex-main',
|
||||
arbiter_service_id: null,
|
||||
activated_at: '2026-03-28T10:00:00.000Z',
|
||||
reason: 'claude-429',
|
||||
explicit: true,
|
||||
@@ -44,6 +47,31 @@ describe('buildRoomRoleContext', () => {
|
||||
ownerServiceId: 'codex-review',
|
||||
reviewerServiceId: 'codex-main',
|
||||
failoverOwner: true,
|
||||
arbiterServiceId: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('returns arbiter context when service matches arbiter_service_id', () => {
|
||||
expect(
|
||||
buildRoomRoleContext(
|
||||
{
|
||||
chat_jid: 'group@test',
|
||||
owner_service_id: 'codex-main',
|
||||
reviewer_service_id: 'claude',
|
||||
arbiter_service_id: 'codex-review',
|
||||
activated_at: null,
|
||||
reason: null,
|
||||
explicit: false,
|
||||
},
|
||||
'codex-review',
|
||||
),
|
||||
).toEqual({
|
||||
serviceId: 'codex-review',
|
||||
role: 'arbiter',
|
||||
ownerServiceId: 'codex-main',
|
||||
reviewerServiceId: 'claude',
|
||||
failoverOwner: false,
|
||||
arbiterServiceId: 'codex-review',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,6 +82,7 @@ describe('buildRoomRoleContext', () => {
|
||||
chat_jid: 'solo@test',
|
||||
owner_service_id: 'codex-main',
|
||||
reviewer_service_id: null,
|
||||
arbiter_service_id: null,
|
||||
activated_at: null,
|
||||
reason: null,
|
||||
explicit: false,
|
||||
|
||||
Reference in New Issue
Block a user