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:
@@ -23,6 +23,7 @@ import {
|
||||
resolveServiceTaskSessionsPath,
|
||||
} from './group-folder.js';
|
||||
import {
|
||||
readArbiterPrompt,
|
||||
readPairedRoomPrompt,
|
||||
readPlatformPrompt,
|
||||
} from './platform-prompts.js';
|
||||
@@ -527,8 +528,9 @@ export function prepareContainerSessionEnvironment(args: {
|
||||
chatJid: string;
|
||||
isMain: boolean;
|
||||
memoryBriefing?: string;
|
||||
role?: 'reviewer' | 'arbiter';
|
||||
}): void {
|
||||
const { sessionDir, chatJid, isMain, memoryBriefing } = args;
|
||||
const { sessionDir, chatJid, isMain, memoryBriefing, role = 'reviewer' } = args;
|
||||
const projectRoot = process.cwd();
|
||||
|
||||
fs.mkdirSync(sessionDir, { recursive: true });
|
||||
@@ -541,10 +543,12 @@ export function prepareContainerSessionEnvironment(args: {
|
||||
];
|
||||
syncDirectoryEntries(skillSources, path.join(sessionDir, 'skills'));
|
||||
|
||||
// Build CLAUDE.md with reviewer-appropriate prompts
|
||||
// Build CLAUDE.md with role-appropriate prompts (reviewer or arbiter)
|
||||
const claudePlatformPrompt = readPlatformPrompt('claude-code', projectRoot);
|
||||
const claudePairedRoomPrompt = isPairedRoomJid(chatJid)
|
||||
? readPairedRoomPrompt('claude-code', projectRoot)
|
||||
? (role === 'arbiter'
|
||||
? readArbiterPrompt(projectRoot)
|
||||
: readPairedRoomPrompt('claude-code', projectRoot))
|
||||
: undefined;
|
||||
const globalDir = path.join(GROUPS_DIR, 'global');
|
||||
const globalClaudeMdPath = path.join(globalDir, 'CLAUDE.md');
|
||||
|
||||
Reference in New Issue
Block a user