profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
demo-fixtures.test.ts 2,589 bytes
1 import { describe, expect, it } from 'vitest';
2 import { buildDebateResult, FIXTURES, resultToStageEvents } from './demo-fixtures';
3
4 describe('demo fixtures', () => {
5 it('ships at least two hand-authored debates', () => {
6 expect(FIXTURES.length).toBeGreaterThanOrEqual(2);
7 });
8
9 for (const spec of FIXTURES) {
10 describe(spec.question.slice(0, 40), () => {
11 const result = buildDebateResult(spec);
12
13 it('has one distinct initial answer per model', () => {
14 expect(result.initialAnswers).toHaveLength(spec.models.length);
15 const unique = new Set(result.initialAnswers.map((a) => a.content));
16 expect(unique.size).toBe(result.initialAnswers.length);
17 });
18
19 it('produces a synthesis and non-zero cost attributed per model', () => {
20 expect(result.synthesis).not.toBeNull();
21 expect(result.synthesis!.finalAnswer.length).toBeGreaterThan(20);
22 expect(result.totals.costUsd).toBeGreaterThan(0);
23 expect(Object.keys(result.totals.costByModel).length).toBeGreaterThanOrEqual(spec.models.length);
24 });
25
26 it('marks convergence.converged consistently with the threshold', () => {
27 const threshold = spec.convergenceThreshold ?? 85;
28 for (const round of result.rounds) {
29 expect(round.convergence!.converged).toBe(round.convergence!.score >= threshold);
30 }
31 });
32
33 it('final answers reflect the last revision content', () => {
34 const lastRound = result.rounds.at(-1)!;
35 for (const rev of lastRound.revisions) {
36 const final = result.finalAnswers.find((a) => a.participantId === rev.participantId);
37 expect(final?.content).toBe(rev.content);
38 }
39 });
40
41 it('critique reviews resolve to real, non-self participants', () => {
42 const ids = new Set(result.participants.map((p) => p.id));
43 for (const round of result.rounds) {
44 for (const c of round.critiques) {
45 for (const r of c.reviews) {
46 expect(ids.has(r.targetParticipantId)).toBe(true);
47 expect(r.targetParticipantId).not.toBe(c.reviewerParticipantId);
48 }
49 }
50 }
51 });
52
53 it('serializes to the expected durable events', () => {
54 const events = resultToStageEvents(result);
55 const count = (t: string) => events.filter((e) => e.type === t).length;
56 expect(count('answer_completed')).toBe(spec.models.length);
57 expect(count('synthesis_completed')).toBe(1);
58 expect(count('convergence_result')).toBe(result.rounds.length);
59 });
60 });
61 }
62 });
63