profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM

Commit

compare peer predictions within the same round only

commit 63ff2ec

3 changed files with +33 and −3

Jump to a changed file
  1. src/components/debate/critique-matrix.tsx +8 −1
  2. src/core/scoring.test.ts +9 −0
  3. src/core/scoring.ts +16 −2
modified src/components/debate/critique-matrix.tsx +8 −1
@@ -88,7 +88,14 @@export function CritiqueMatrix({
88 88 </th>
89 89 ))}
90 90 <th className="p-1 text-xs font-medium text-muted-foreground">avg&nbsp;recv</th>
91 - {predictions.any && <th className="p-1 text-xs font-medium text-muted-foreground">council&nbsp;read</th>}
91 + {predictions.any && (
92 + <th
93 + className="p-1 text-xs font-medium text-muted-foreground"
94 + title="Mean error of this reviewer's council-average predictions in this round; lower reads the council better"
95 + >
96 + council&nbsp;read
97 + </th>
98 + )}
92 99 </tr>
93 100 </thead>
94 101 <tbody>
modified src/core/scoring.test.ts +9 −0
@@ -122,6 +122,15 @@describe('buildPredictionCells', () => {
122 122 const critiques = [critiqueWithPredictions('p0', { p1: { score: 5 } })];
123 123 expect(buildPredictionCells(participants, critiques)).toHaveLength(0);
124 124 });
125 +
126 + it('compares predictions only against scores from the same round', () => {
127 + const round1 = critiqueWithPredictions('p0', { p2: { score: 3, predicted: 7 } });
128 + const round1Peer = critiqueWithPredictions('p1', { p2: { score: 8 } });
129 + const round2Peer = { ...critiqueWithPredictions('p1', { p2: { score: 4 } }), round: 2 };
130 + const cells = buildPredictionCells(participants, [round1, round1Peer, round2Peer]);
131 + // The round-1 prediction must see round-1's 8, not round-2's 4.
132 + expect(cells[0]!.actualPeerMean).toBe(8);
133 + });
125 134 });
126 135
127 136 describe('classifyPrediction', () => {
modified src/core/scoring.ts +16 −2
@@ -98,15 +98,29 @@export function classifyPrediction(cell: PredictionCell): PredictionReading | nu
98 98 : 'miscalibrated';
99 99 }
100 100
101 -/** One cell per review that carried a `predictedPeerMean`. */
101 +/**
102 + * One cell per review that carried a `predictedPeerMean`. Predictions are
103 + * compared against the scores from the SAME round only - mixing rounds would
104 + * judge a round-1 prediction against a round-2 consensus.
105 + */
102 106 export function buildPredictionCells(
103 107 participants: Participant[],
104 108 critiques: CritiqueRecord[],
105 109 ): PredictionCell[] {
106 - const matrix = buildScoreMatrix(participants, critiques);
110 + const matrixByRound = new Map<number, ScoreMatrix>();
111 + const matrixFor = (round: number): ScoreMatrix => {
112 + let m = matrixByRound.get(round);
113 + if (!m) {
114 + m = buildScoreMatrix(participants, critiques.filter((c) => c.round === round));
115 + matrixByRound.set(round, m);
116 + }
117 + return m;
118 + };
119 +
107 120 const cells: PredictionCell[] = [];
108 121 for (const critique of critiques) {
109 122 const reviewerId = critique.reviewerParticipantId;
123 + const matrix = matrixFor(critique.round);
110 124 if (!matrix.cells[reviewerId]) continue;
111 125 for (const review of critique.reviews) {
112 126 if (review.predictedPeerMean === undefined) continue;