profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
debate-registry.ts 1,612 bytes
1 /**
2 * Registry of in-flight debates so explicit user controls can reach a run
3 * server-side:
4 * - cancel: abort everything (the run ends as 'aborted')
5 * - gavel: conclude gracefully - finish the current phase, skip remaining
6 * rounds, and go straight to synthesis
7 *
8 * Note this is intentionally separate from client disconnect: a browser going
9 * away does NOT abort the debate (graceful resume), but hitting the cancel
10 * endpoint does. Process-local, which is fine for the single-VPS deployment.
11 */
12 interface RunningDebate {
13 abort: AbortController;
14 gavel: AbortController;
15 }
16
17 const running = new Map<string, RunningDebate>();
18
19 export function registerDebate(id: string, handles: RunningDebate): void {
20 running.set(id, handles);
21 }
22
23 export function unregisterDebate(id: string): void {
24 running.delete(id);
25 }
26
27 export function isDebateRunning(id: string): boolean {
28 return running.has(id);
29 }
30
31 /** Abort a running debate. Returns false if it wasn't running here. */
32 export function cancelDebate(id: string): boolean {
33 const handles = running.get(id);
34 if (!handles) return false;
35 handles.abort.abort(new Error('Debate cancelled by user'));
36 running.delete(id);
37 return true;
38 }
39
40 /**
41 * Conclude a running debate early: remaining rounds are skipped and the
42 * chairman synthesizes what exists. The debate stays registered - it is still
43 * running (synthesis) until the run loop unregisters it.
44 */
45 export function gavelDebate(id: string): boolean {
46 const handles = running.get(id);
47 if (!handles) return false;
48 handles.gavel.abort(new Error('Gavel: conclude now'));
49 return true;
50 }
51