@@ -164,7 +164,6 @@ <h1>ENKI Debate Arena</h1>
164164const STOP_WORDS = new Set ( [ 'a' , 'an' , 'the' , 'in' , 'on' , 'of' , 'to' , 'is' , 'it' , 'or' , 'and' , 'was' , 'who' , 'how' , 'do' , 'does' , 'what' ] ) ;
165165function searchCorpus ( kw , corpus ) { const m = kw . filter ( k => k . length >= 3 && ! STOP_WORDS . has ( k ) ) ; if ( ! m . length ) return [ ] ; return corpus . filter ( e => e . k . some ( k => m . some ( q => q === k || ( q . length >= 4 && k . length >= 4 && ( k . includes ( q ) || q . includes ( k ) ) ) ) ) ) . map ( e => ( { source :e . s , text :e . t , location :e . l } ) ) ; }
166166function dedupe ( c ) { const s = new Set ( ) ; return c . filter ( e => { const k = e . source + ':' + e . location ; if ( s . has ( k ) ) return false ; s . add ( k ) ; return true ; } ) ; }
167- function pickRandom ( arr ) { return arr [ Math . floor ( Math . random ( ) * arr . length ) ] ; }
168167let wormSeq = 0 , wormChain = [ ] ;
169168async function sha256 ( s ) { const b = new TextEncoder ( ) . encode ( s ) ; const h = await crypto . subtle . digest ( 'SHA-256' , b ) ; return Array . from ( new Uint8Array ( h ) ) . map ( b => b . toString ( 16 ) . padStart ( 2 , '0' ) ) . join ( '' ) ; }
170169async function sealWorm ( eid , ag , act , v , cit ) { wormSeq ++ ; const prev = wormChain . length === 0 ?'GENESIS' :wormChain [ wormChain . length - 1 ] . hash ; const ts = new Date ( ) . toISOString ( ) ; const hash = await sha256 ( `${ wormSeq } |${ prev } |${ eid } |${ ag } |${ act } |${ v } |${ ts } ` ) ; const e = { seq :wormChain . length + 1 , prev_hash :prev , hash, timestamp :ts , event_id :eid , agent :ag , action :act , verdict :v , citations :cit } ; wormChain . push ( e ) ; return { sequence :e . seq , hash :e . hash , sealed :true } ; }
@@ -261,83 +260,182 @@ <h1>ENKI Debate Arena</h1>
261260 document . getElementById ( 'rounds' ) . appendChild ( el ) ;
262261}
263262
264- async function runDebate ( ) {
265- const q = document . getElementById ( 'question' ) . value . trim ( ) ; if ( ! q ) return ;
266- const loading = document . getElementById ( 'loading' ) , roundsEl = document . getElementById ( 'rounds' ) , scoresEl = document . getElementById ( 'scores' ) , verdictBar = document . getElementById ( 'verdict-bar' ) ;
267- roundsEl . innerHTML = '' ; loading . classList . add ( 'visible' ) ; scoresEl . style . display = 'none' ; verdictBar . style . display = 'none' ;
268- document . querySelectorAll ( '.pipe-step' ) . forEach ( el => el . className = 'pipe-step' ) ;
263+ // --- Pipeline state ---
264+ let debateMode = 'idle' ; // idle|debate|step|auto
265+ let autoTimer = null ;
266+ let currentQuestion = '' ;
267+ let pipelineSteps = [ ] ;
268+ let stepIndex = 0 ;
269+ let pipelineData = { } ;
270+
271+ const STEP_DELAY = { debate :150 , auto :800 } ;
272+
273+ function cancelPipeline ( ) {
274+ debateMode = 'idle' ;
275+ if ( autoTimer ) { clearTimeout ( autoTimer ) ; autoTimer = null ; }
276+ document . getElementById ( 'loading' ) . classList . remove ( 'visible' ) ;
277+ document . getElementById ( 'debate-btn' ) . textContent = 'Debate' ;
278+ document . getElementById ( 'debate-btn' ) . disabled = false ;
279+ document . getElementById ( 'step-btn' ) . textContent = 'Step Through' ;
280+ document . getElementById ( 'step-btn' ) . disabled = false ;
281+ document . getElementById ( 'auto-btn' ) . textContent = 'Auto Play' ;
282+ document . getElementById ( 'auto-btn' ) . disabled = false ;
283+ }
284+
285+ function showStepButtons ( mode ) {
286+ const d = document . getElementById ( 'debate-btn' ) ;
287+ const s = document . getElementById ( 'step-btn' ) ;
288+ const a = document . getElementById ( 'auto-btn' ) ;
289+ if ( mode === 'step' ) {
290+ d . textContent = 'Debate' ; d . disabled = false ;
291+ s . textContent = 'Next Step' ; s . disabled = false ; a . disabled = true ; a . textContent = 'Auto Play' ;
292+ } else if ( mode === 'auto' ) {
293+ d . textContent = 'Debate' ; d . disabled = false ;
294+ s . textContent = 'Pause' ; s . disabled = false ; a . textContent = 'Stop' ; a . disabled = false ;
295+ } else {
296+ d . textContent = 'Debate' ; d . disabled = false ;
297+ s . textContent = 'Step Through' ; s . disabled = false ;
298+ a . textContent = 'Auto Play' ; a . disabled = false ;
299+ }
300+ }
269301
302+ async function sleep ( ms ) { return new Promise ( r => setTimeout ( r , ms ) ) ; }
303+
304+ async function advanceStep ( ) {
305+ if ( stepIndex >= pipelineSteps . length ) return finishPipeline ( ) ;
306+ const step = pipelineSteps [ stepIndex ] ;
307+ stepIndex ++ ;
308+ await executeStep ( step ) ;
309+ if ( debateMode === 'auto' ) {
310+ if ( stepIndex >= pipelineSteps . length ) return finishPipeline ( ) ;
311+ autoTimer = setTimeout ( ( ) => advanceStep ( ) , STEP_DELAY . auto ) ;
312+ } else if ( debateMode === 'step' ) {
313+ if ( stepIndex >= pipelineSteps . length ) return finishPipeline ( ) ;
314+ document . getElementById ( 'step-btn' ) . textContent = `Next Step (${ stepIndex } /${ pipelineSteps . length } )` ;
315+ } else {
316+ await sleep ( STEP_DELAY . debate ) ;
317+ advanceStep ( ) ;
318+ }
319+ }
320+
321+ async function executeStep ( step ) {
322+ const q = currentQuestion ;
270323 const kw = q . toLowerCase ( ) . split ( / \s + / ) ;
271324 const meaningfulKw = kw . filter ( k => k . length >= 3 && ! STOP_WORDS . has ( k ) ) ;
272325
273- // SCRIBE
274- setStep ( 'scribe' , 'active' ) ;
275- await new Promise ( r => setTimeout ( r , 200 ) ) ;
276- const cites = dedupe ( [ ...searchCorpus ( meaningfulKw , BIBLE ) , ...searchCorpus ( meaningfulKw , ENOCH ) , ...searchCorpus ( meaningfulKw , THEOLOGY ) ] ) ;
277- const scribeConf = cites . length > 0 ?Math . min ( 0.4 + cites . length * 0.12 , 0.95 ) :0.15 ;
278- setStep ( 'scribe' , 'done' ) ;
279-
280- // JUDGE
281- setStep ( 'judge' , 'active' ) ;
282- await new Promise ( r => setTimeout ( r , 200 ) ) ;
283- const judgeVerdict = cites . length > 0 ?'approve' :'repent' ;
284- setStep ( 'judge' , 'done' ) ;
285-
286- // ENKI
287- setStep ( 'enki' , 'active' ) ;
288- await new Promise ( r => setTimeout ( r , 300 ) ) ;
289- const enkiMatch = ENKI_DB . find ( e => q . toLowerCase ( ) . includes ( e . topic ) ) || { topic :q , tension :`The nature of "${ q } " involves multiple domains.` , synthesis :`Understanding "${ q } " requires cross-domain analysis.` , label :'hypothesis' } ;
290- const enkiConf = Math . min ( 0.3 + cites . length * 0.1 , 0.7 ) ;
291- setStep ( 'enki' , 'done' ) ;
292-
293- // ADVERSARY
294- setStep ( 'adversary' , 'active' ) ;
295- await new Promise ( r => setTimeout ( r , 200 ) ) ;
296- const advChallenges = [ ] ;
297- if ( enkiConf > 0.6 && enkiMatch . label !== 'fact' ) advChallenges . push ( { type :'overclaiming' , description :'Confidence exceeds threshold for non-fact synthesis' , severity :'high' } ) ;
298- if ( enkiMatch . label === 'analogy' ) advChallenges . push ( { type :'weak_analogy' , description :'Analogy may not be structurally sound' , severity :'medium' } ) ;
299- const advPassed = advChallenges . filter ( c => c . severity === 'high' ) . length < 2 ;
300- setStep ( 'adversary' , advPassed ?'done' :'attacked' ) ;
301-
302- // MISCONCEPTION
303- setStep ( 'misconception' , 'active' ) ;
304- await new Promise ( r => setTimeout ( r , 200 ) ) ;
305- const misconceptions = misconceptionCheck ( enkiMatch . synthesis ) ;
306- setStep ( 'misconception' , misconceptions . length > 0 ?'attacked' :'done' ) ;
307-
308- // NOISE
309- setStep ( 'noise' , 'active' ) ;
310- await new Promise ( r => setTimeout ( r , 200 ) ) ;
311- const noise = noiseCheck ( enkiMatch . synthesis ) ;
312- setStep ( 'noise' , noise . length > 0 ?'attacked' :'done' ) ;
313-
314- // PROPHET
315- setStep ( 'prophet' , 'active' ) ;
316- await new Promise ( r => setTimeout ( r , 200 ) ) ;
317- const risk = misconceptions . some ( m => m . severity === 'high' ) || noise . some ( n => n . severity === 'high' ) ?'high' :advChallenges . length > 0 ?'medium' :'none' ;
318- setStep ( 'prophet' , 'done' ) ;
319-
320- // SENTINEL
321- setStep ( 'sentinel' , 'active' ) ;
322- await new Promise ( r => setTimeout ( r , 200 ) ) ;
323- const classification = classifyClaim ( enkiMatch . label , advPassed , misconceptions , noise ) ;
324- const sentinelAllowed = classification !== 'misconception' && classification !== 'noise' && classification !== 'blocked' ;
325- setStep ( 'sentinel' , sentinelAllowed ?'done' :'blocked' ) ;
326-
327- // LEDGE
328- setStep ( 'ledge' , 'active' ) ;
329- let ledgeResult = null ;
330- if ( sentinelAllowed ) { await new Promise ( r => setTimeout ( r , 200 ) ) ; ledgeResult = await sealWorm ( `debate_${ Date . now ( ) . toString ( 36 ) } ` , 'ARENA' , q , judgeVerdict , cites . map ( c => c . source ) ) ; }
331- setStep ( 'ledge' , ledgeResult ?'done' :'blocked' ) ;
332-
333- const scores = computeScores ( cites . length , { label :enkiMatch . label } , { passed :advPassed } , misconceptions , noise ) ;
334- const verdict = computeVerdict ( scores , classification , advPassed ) ;
335-
336- const round = { round :1 , question :q , scribe :{ citations :cites , confidence :scribeConf } , enki :{ claim :enkiMatch . topic , synthesis :enkiMatch . synthesis , synthesis_label :enkiMatch . label , confidence :enkiConf , tensionMap :null } , adversary :{ passed :advPassed , challenges :advChallenges , verdict :advPassed ?'approve' :'repent' } , misconception :misconceptions , noise, judge :{ verdict :judgeVerdict , violatedRules :[ ] , leanCheck :cites . length > 0 } , prophet :{ riskLevel :risk , warnings :[ ] , recommendation :risk === 'high' ?'reject' :'proceed' } , sentinel :{ allowed :sentinelAllowed , reason :sentinelAllowed ?'Passed' :'Blocked' , classification} , ledge :ledgeResult , scores, verdict} ;
337-
338- loading . classList . remove ( 'visible' ) ;
326+ switch ( step ) {
327+ case 'scribe' :{
328+ setStep ( 'scribe' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
329+ const cites = dedupe ( [ ...searchCorpus ( meaningfulKw , BIBLE ) , ...searchCorpus ( meaningfulKw , ENOCH ) , ...searchCorpus ( meaningfulKw , THEOLOGY ) ] ) ;
330+ const scribeConf = cites . length > 0 ?Math . min ( 0.4 + cites . length * 0.12 , 0.95 ) :0.15 ;
331+ pipelineData . cites = cites ; pipelineData . scribeConf = scribeConf ;
332+ setStep ( 'scribe' , 'done' ) ;
333+ showAgentMsg ( 'scribe' , '🔍📖' , 'SCRIBE' , `Found <strong>${ cites . length } </strong> citation(s). Confidence: <strong>${ scribeConf } </strong>` ) ;
334+ break ; }
335+ case 'judge' :{
336+ setStep ( 'judge' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
337+ const judgeVerdict = pipelineData . cites . length > 0 ?'approve' :'repent' ;
338+ pipelineData . judgeVerdict = judgeVerdict ;
339+ setStep ( 'judge' , 'done' ) ;
340+ showAgentMsg ( 'judge' , '⚖️' , 'JUDGE' , `Verdict: <strong>${ judgeVerdict } </strong>. Lean: ${ pipelineData . cites . length > 0 ?'✓' :'✗' } ` ) ;
341+ break ; }
342+ case 'enki' :{
343+ setStep ( 'enki' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
344+ const enkiMatch = ENKI_DB . find ( e => q . toLowerCase ( ) . includes ( e . topic ) ) || { topic :q , tension :`The nature of "${ q } " involves multiple domains.` , synthesis :`Understanding "${ q } " requires cross-domain analysis.` , label :'hypothesis' } ;
345+ const enkiConf = Math . min ( 0.3 + pipelineData . cites . length * 0.1 , 0.7 ) ;
346+ pipelineData . enkiMatch = enkiMatch ; pipelineData . enkiConf = enkiConf ;
347+ setStep ( 'enki' , 'done' ) ;
348+ showAgentMsg ( 'enki' , '🔮' , 'ENKI' , `<strong>${ enkiMatch . topic } </strong><br>${ enkiMatch . synthesis } <br><span class="claim-badge ${ enkiMatch . label } ">${ enkiMatch . label } </span>` ) ;
349+ break ; }
350+ case 'adversary' :{
351+ setStep ( 'adversary' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
352+ const advChallenges = [ ] ;
353+ if ( pipelineData . enkiConf > 0.6 && pipelineData . enkiMatch . label !== 'fact' ) advChallenges . push ( { type :'overclaiming' , description :'Confidence exceeds threshold for non-fact synthesis' , severity :'high' } ) ;
354+ if ( pipelineData . enkiMatch . label === 'analogy' ) advChallenges . push ( { type :'weak_analogy' , description :'Analogy may not be structurally sound' , severity :'medium' } ) ;
355+ const advPassed = advChallenges . filter ( c => c . severity === 'high' ) . length < 2 ;
356+ pipelineData . advChallenges = advChallenges ; pipelineData . advPassed = advPassed ;
357+ setStep ( 'adversary' , advPassed ?'done' :'attacked' ) ;
358+ if ( advChallenges . length > 0 ) {
359+ let h = '' ; advChallenges . forEach ( c => { h += `<div class="challenge">[${ c . type } ] ${ c . description } </div>` ; } ) ;
360+ h += `<div style="margin-top:6px">Passed: <strong>${ advPassed } </strong></div>` ;
361+ showAgentMsg ( 'adversary' , '⚔️' , 'ADVERSARY' , h ) ;
362+ } else {
363+ showAgentMsg ( 'adversary' , '⚔️' , 'ADVERSARY' , `No challenges. Passed: <strong>true</strong>` ) ;
364+ }
365+ break ; }
366+ case 'misconception' :{
367+ setStep ( 'misconception' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
368+ const misconceptions = misconceptionCheck ( pipelineData . enkiMatch . synthesis ) ;
369+ pipelineData . misconceptions = misconceptions ;
370+ setStep ( 'misconception' , misconceptions . length > 0 ?'attacked' :'done' ) ;
371+ if ( misconceptions . length > 0 ) {
372+ let h = '' ; misconceptions . forEach ( m => { h += `<div class="misconception-inject">[${ m . classification } ] ${ m . reason } </div>` ; } ) ;
373+ showAgentMsg ( 'misconception' , '🎭' , 'MISCONCEPTION' , h ) ;
374+ } else {
375+ showAgentMsg ( 'misconception' , '🎭' , 'MISCONCEPTION' , 'No reasoning errors detected.' ) ;
376+ }
377+ break ; }
378+ case 'noise' :{
379+ setStep ( 'noise' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
380+ const noise = noiseCheck ( pipelineData . enkiMatch . synthesis ) ;
381+ pipelineData . noise = noise ;
382+ setStep ( 'noise' , noise . length > 0 ?'attacked' :'done' ) ;
383+ if ( noise . length > 0 ) {
384+ let h = '' ; noise . forEach ( n => { h += `<div class="noise-inject">[${ n . type } ] ${ n . desc } </div>` ; } ) ;
385+ showAgentMsg ( 'noise' , '🦠' , 'NOISE' , h ) ;
386+ } else {
387+ showAgentMsg ( 'noise' , '🦠' , 'NOISE' , 'No noise detected.' ) ;
388+ }
389+ break ; }
390+ case 'prophet' :{
391+ setStep ( 'prophet' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
392+ const risk = pipelineData . misconceptions . some ( m => m . severity === 'high' ) || pipelineData . noise . some ( n => n . severity === 'high' ) ?'high' :pipelineData . advChallenges . length > 0 ?'medium' :'none' ;
393+ pipelineData . risk = risk ;
394+ setStep ( 'prophet' , 'done' ) ;
395+ showAgentMsg ( 'prophet' , '🔥' , 'PROPHET' , `Risk: <strong>${ risk } </strong>. Recommendation: ${ risk === 'high' ?'reject' :'proceed' } ` ) ;
396+ break ; }
397+ case 'sentinel' :{
398+ setStep ( 'sentinel' , 'active' ) ; await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
399+ const classification = classifyClaim ( pipelineData . enkiMatch . label , pipelineData . advPassed , pipelineData . misconceptions , pipelineData . noise ) ;
400+ const sentinelAllowed = classification !== 'misconception' && classification !== 'noise' && classification !== 'blocked' ;
401+ pipelineData . classification = classification ; pipelineData . sentinelAllowed = sentinelAllowed ;
402+ setStep ( 'sentinel' , sentinelAllowed ?'done' :'blocked' ) ;
403+ const el = document . createElement ( 'div' ) ;
404+ el . className = `sentinel-class ${ classification } ` ;
405+ el . textContent = `SENTINEL: ${ classification . toUpperCase ( ) } ` ;
406+ document . getElementById ( 'rounds' ) . appendChild ( el ) ;
407+ break ; }
408+ case 'ledge' :{
409+ setStep ( 'ledge' , 'active' ) ;
410+ let ledgeResult = null ;
411+ if ( pipelineData . sentinelAllowed ) {
412+ await sleep ( debateMode === 'debate' ?STEP_DELAY . debate :100 ) ;
413+ ledgeResult = await sealWorm ( `debate_${ Date . now ( ) . toString ( 36 ) } ` , 'ARENA' , q , pipelineData . judgeVerdict , pipelineData . cites . map ( c => c . source ) ) ;
414+ }
415+ pipelineData . ledgeResult = ledgeResult ;
416+ setStep ( 'ledge' , ledgeResult ?'done' :'blocked' ) ;
417+ break ; }
418+ }
419+ }
420+
421+ function showAgentMsg ( agentId , emoji , name , html ) {
422+ const el = document . createElement ( 'div' ) ;
423+ el . className = 'agent-msg' ;
424+ el . innerHTML = `<div class="agent-name"><span class="emoji">${ emoji } </span> ${ name } </div><div class="msg-text">${ html } </div>` ;
425+ document . getElementById ( 'rounds' ) . appendChild ( el ) ;
426+ }
427+
428+ function finishPipeline ( ) {
429+ const d = pipelineData ;
430+ const scores = computeScores ( d . cites . length , { label :d . enkiMatch . label } , { passed :d . advPassed } , d . misconceptions , d . noise ) ;
431+ const verdict = computeVerdict ( scores , d . classification , d . advPassed ) ;
432+
433+ const round = { round :1 , question :currentQuestion , scribe :{ citations :d . cites , confidence :d . scribeConf } , enki :{ claim :d . enkiMatch . topic , synthesis :d . enkiMatch . synthesis , synthesis_label :d . enkiMatch . label , confidence :d . enkiConf , tensionMap :null } , adversary :{ passed :d . advPassed , challenges :d . advChallenges , verdict :d . advPassed ?'approve' :'repent' } , misconception :d . misconceptions , noise :d . noise , judge :{ verdict :d . judgeVerdict , violatedRules :[ ] , leanCheck :d . cites . length > 0 } , prophet :{ riskLevel :d . risk , warnings :[ ] , recommendation :d . risk === 'high' ?'reject' :'proceed' } , sentinel :{ allowed :d . sentinelAllowed , reason :d . sentinelAllowed ?'Passed' :'Blocked' , classification :d . classification } , ledge :d . ledgeResult , scores, verdict} ;
434+
435+ document . getElementById ( 'loading' ) . classList . remove ( 'visible' ) ;
436+ const scoresEl = document . getElementById ( 'scores' ) ;
339437 scoresEl . style . display = 'flex' ;
340- verdictBar . style . display = 'flex' ;
438+ document . getElementById ( 'verdict-bar' ) . style . display = 'flex' ;
341439
342440 document . getElementById ( 'sc-ev' ) . textContent = scores . evidence ; document . getElementById ( 'sc-ev' ) . className = 'score-value ' + scoreClass ( scores . evidence ) ;
343441 document . getElementById ( 'sc-lg' ) . textContent = scores . logic ; document . getElementById ( 'sc-lg' ) . className = 'score-value ' + scoreClass ( scores . logic ) ;
@@ -347,16 +445,44 @@ <h1>ENKI Debate Arena</h1>
347445
348446 document . getElementById ( 'final-verdict' ) . textContent = verdict . replace ( / _ / g, ' ' ) ;
349447 document . getElementById ( 'final-verdict' ) . className = 'verdict-value ' + verdict ;
350- document . getElementById ( 'total-claims' ) . textContent = '1 claim · ' + classification ;
448+ document . getElementById ( 'total-claims' ) . textContent = '1 claim · ' + d . classification ;
351449
352450 renderRound ( round ) ;
451+ debateMode = 'idle' ;
452+ showStepButtons ( 'idle' ) ;
453+ }
454+
455+ async function startDebate ( mode ) {
456+ const q = document . getElementById ( 'question' ) . value . trim ( ) ; if ( ! q ) return ;
457+ if ( debateMode !== 'idle' ) cancelPipeline ( ) ;
458+ currentQuestion = q ;
459+ debateMode = mode ;
460+ pipelineSteps = [ 'scribe' , 'judge' , 'enki' , 'adversary' , 'misconception' , 'noise' , 'prophet' , 'sentinel' , 'ledge' ] ;
461+ stepIndex = 0 ;
462+ pipelineData = { } ;
463+
464+ document . getElementById ( 'rounds' ) . innerHTML = '' ;
465+ document . getElementById ( 'loading' ) . classList . add ( 'visible' ) ;
466+ document . getElementById ( 'scores' ) . style . display = 'none' ;
467+ document . getElementById ( 'verdict-bar' ) . style . display = 'none' ;
468+ document . querySelectorAll ( '.pipe-step' ) . forEach ( el => el . className = 'pipe-step' ) ;
469+
470+ showStepButtons ( mode ) ;
471+ await advanceStep ( ) ;
353472}
354473
355- document . querySelectorAll ( '.example' ) . forEach ( el => { el . addEventListener ( 'click' , ( ) => { document . getElementById ( 'question' ) . value = el . dataset . q ; runDebate ( ) ; } ) ; } ) ;
356- document . getElementById ( 'debate-btn' ) . addEventListener ( 'click' , runDebate ) ;
357- document . getElementById ( 'step-btn' ) . addEventListener ( 'click' , runDebate ) ;
358- document . getElementById ( 'auto-btn' ) . addEventListener ( 'click' , runDebate ) ;
359- document . getElementById ( 'question' ) . addEventListener ( 'keydown' , e => { if ( e . key === 'Enter' ) runDebate ( ) ; } ) ;
474+ document . querySelectorAll ( '.example' ) . forEach ( el => { el . addEventListener ( 'click' , ( ) => { document . getElementById ( 'question' ) . value = el . dataset . q ; startDebate ( 'debate' ) ; } ) ; } ) ;
475+ document . getElementById ( 'debate-btn' ) . addEventListener ( 'click' , ( ) => { if ( debateMode === 'idle' ) startDebate ( 'debate' ) ; } ) ;
476+ document . getElementById ( 'step-btn' ) . addEventListener ( 'click' , ( ) => {
477+ if ( debateMode === 'idle' ) startDebate ( 'step' ) ;
478+ else if ( debateMode === 'step' ) { advanceStep ( ) ; }
479+ else if ( debateMode === 'auto' ) { cancelPipeline ( ) ; startDebate ( 'step' ) ; }
480+ } ) ;
481+ document . getElementById ( 'auto-btn' ) . addEventListener ( 'click' , ( ) => {
482+ if ( debateMode === 'idle' ) startDebate ( 'auto' ) ;
483+ else if ( debateMode === 'step' || debateMode === 'auto' ) cancelPipeline ( ) ;
484+ } ) ;
485+ document . getElementById ( 'question' ) . addEventListener ( 'keydown' , e => { if ( e . key === 'Enter' ) { if ( debateMode === 'idle' ) startDebate ( 'debate' ) ; } } ) ;
360486</ script >
361487</ body >
362488</ html >
0 commit comments