diff --git a/scripts/backfill-binary-decision.ts b/scripts/backfill-binary-decision.ts
new file mode 100644
index 0000000..82fb608
--- /dev/null
+++ b/scripts/backfill-binary-decision.ts
@@ -0,0 +1,84 @@
+/**
+ * One-off script: backfill binaryDecision from custom boolean criterion
+ * "Move to the Next Stage?" for evaluations where binaryDecision is null.
+ *
+ * Usage: npx tsx scripts/backfill-binary-decision.ts
+ *
+ * What it does:
+ * 1. Finds all rounds with a boolean criterion labeled "Move to the Next Stage?"
+ * 2. For evaluations in those rounds where binaryDecision IS NULL,
+ * copies the boolean value from criterionScoresJson into binaryDecision
+ */
+
+import { PrismaClient } from '@prisma/client'
+
+const prisma = new PrismaClient()
+
+type CriterionConfig = {
+ id: string
+ label: string
+ type?: string
+}
+
+async function main() {
+ // Find all rounds that have evaluation config with criteria
+ const rounds = await prisma.round.findMany({
+ where: { roundType: 'EVALUATION' },
+ select: { id: true, name: true, configJson: true },
+ })
+
+ let totalUpdated = 0
+
+ for (const round of rounds) {
+ const config = round.configJson as Record | null
+ if (!config) continue
+
+ const criteria = (config.criteria ?? config.evaluationCriteria ?? []) as CriterionConfig[]
+
+ // Find the boolean criterion for "Move to the Next Stage?"
+ const boolCriterion = criteria.find(
+ (c) =>
+ (c.type === 'boolean') &&
+ c.label?.toLowerCase().includes('move to the next stage'),
+ )
+
+ if (!boolCriterion) continue
+
+ console.log(`Round "${round.name}" (${round.id}): found criterion "${boolCriterion.label}" (${boolCriterion.id})`)
+
+ // Find evaluations in this round where binaryDecision is null
+ const evaluations = await prisma.evaluation.findMany({
+ where: {
+ assignment: { roundId: round.id },
+ binaryDecision: null,
+ status: 'SUBMITTED',
+ criterionScoresJson: { not: undefined },
+ },
+ select: { id: true, criterionScoresJson: true },
+ })
+
+ let updated = 0
+ for (const ev of evaluations) {
+ const scores = ev.criterionScoresJson as Record | null
+ if (!scores) continue
+
+ const value = scores[boolCriterion.id]
+ if (typeof value !== 'boolean') continue
+
+ await prisma.evaluation.update({
+ where: { id: ev.id },
+ data: { binaryDecision: value },
+ })
+ updated++
+ }
+
+ console.log(` Updated ${updated}/${evaluations.length} evaluations`)
+ totalUpdated += updated
+ }
+
+ console.log(`\nDone. Total evaluations updated: ${totalUpdated}`)
+}
+
+main()
+ .catch(console.error)
+ .finally(() => prisma.$disconnect())
diff --git a/src/components/admin/round/score-distribution.tsx b/src/components/admin/round/score-distribution.tsx
index 6ac8432..f6f84a2 100644
--- a/src/components/admin/round/score-distribution.tsx
+++ b/src/components/admin/round/score-distribution.tsx
@@ -38,13 +38,13 @@ export function ScoreDistribution({ roundId }: ScoreDistributionProps) {
No evaluations submitted yet
) : (
-
+
{dist.globalDistribution.map((bucket) => {
const heightPct = (bucket.count / maxCount) * 100
return (
-