From 51b5208b9b5ac51b7e531ddeb59093c1cb381491 Mon Sep 17 00:00:00 2001 From: YurenHao0426 Date: Sat, 14 Feb 2026 01:31:53 +0000 Subject: Rework debate prompts, add turn-based rounds and self-elimination convergence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Round 1 parallel (form positions), Round 2+ sequential turn-based (each model sees current round's prior responses before speaking) - Prompts treat user question as open-ended, not as a debate proposition — models form their own thesis in Round 1 then defend it - Structured opposition: each model defends own unique position, not FOR/AGAINST - Self-convergence: each model judges if convinced after each round, eliminated models drop out, last one standing wins and provides final summary - Skip convergence/judge checks on Round 1 (still forming positions) - Auto-save now triggers on councilData/debateData updates so intermediate rounds persist across page refresh Co-Authored-By: Claude Opus 4.6 --- frontend/src/components/Sidebar.tsx | 32 ++++++++++++++++++++++---------- frontend/src/store/flowStore.ts | 5 +++-- 2 files changed, 25 insertions(+), 12 deletions(-) (limited to 'frontend') diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index aeb164b..8bb5fcb 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -810,20 +810,32 @@ const Sidebar: React.FC = ({ isOpen, onToggle, onInteract }) => { } break; } - case 'convergence_check': { + case 'model_eliminated': { const lastRound2 = debateRounds[debateRounds.length - 1]; if (lastRound2) { - lastRound2.converged = evt.data.converged; - updateNodeData(runningNodeId, { - debateData: { - rounds: [...debateRounds], - finalVerdict: null, - config: { judgeMode, format: debateFormat, maxRounds }, - }, + if (!lastRound2.eliminated) lastRound2.eliminated = []; + lastRound2.eliminated.push({ + model: evt.data.model, + convincedBy: evt.data.convinced_by, + reasoning: evt.data.reasoning, }); } - if (evt.data.converged) { - setDebateStage('Consensus reached!'); + setDebateStage(`${evt.data.model} concedes to ${evt.data.convinced_by || 'another'}...`); + break; + } + case 'convergence_status': { + const remaining = evt.data.remaining as string[]; + updateNodeData(runningNodeId, { + debateData: { + rounds: [...debateRounds], + finalVerdict: null, + config: { judgeMode, format: debateFormat, maxRounds }, + }, + }); + if (remaining.length <= 1) { + setDebateStage(`${remaining[0] || 'Winner'} is the last one standing!`); + } else { + setDebateStage(`${remaining.length} models remaining...`); } break; } diff --git a/frontend/src/store/flowStore.ts b/frontend/src/store/flowStore.ts index c1c8b99..5bb3e22 100644 --- a/frontend/src/store/flowStore.ts +++ b/frontend/src/store/flowStore.ts @@ -95,7 +95,7 @@ export interface DebateRound { round: number; responses: Array<{ model: string; response: string }>; judgeDecision?: { continue: boolean; reasoning: string }; - converged?: boolean; + eliminated?: Array<{ model: string; convincedBy: string | null; reasoning: string }>; } export interface DebateData { @@ -1063,7 +1063,8 @@ const useFlowStore = create((set, get) => { } // Trigger auto-save for important changes (not just userPrompt typing) - if (data.response !== undefined || data.status !== undefined || data.attachedFileIds !== undefined) { + if (data.response !== undefined || data.status !== undefined || data.attachedFileIds !== undefined + || data.councilData !== undefined || data.debateData !== undefined) { get().triggerAutoSave(); } }, -- cgit v1.2.3