diff --git a/docs/plans/2026-02-25-advance-criterion-design.md b/docs/plans/2026-02-25-advance-criterion-design.md new file mode 100644 index 0000000..2e7a981 --- /dev/null +++ b/docs/plans/2026-02-25-advance-criterion-design.md @@ -0,0 +1,108 @@ +# Advance Criterion & Juror Progress Dashboard + +**Date:** 2026-02-25 +**Status:** Approved + +## Problem + +Jurors have no visibility into their evaluation progress — specifically how many YES/NO advancement decisions they've made and for which projects. Admins similarly lack a quick summary of advancement votes across the jury. + +## Solution + +A new `advance` criterion type, a juror-facing progress dashboard, and admin dashboard enhancements. + +## Design + +### 1. New Criterion Type: `advance` + +Added alongside `numeric`, `text`, `boolean`, `section_header`. + +**Shape in `criteriaJson`:** + +```ts +{ + id: string, + label: string, // default "Advance to next round?" + description?: string, + type: "advance", + trueLabel: string, // default "Yes" + falseLabel: string, // default "No" + required: true // always required, not configurable +} +``` + +**Storage:** `criterionScoresJson` as `{ [criterionId]: true | false }`. + +**Constraints:** +- Max one per `EvaluationForm` (enforced in form builder UI and server-side on upsert) +- Always `required: true` +- No `weight` — does not factor into numeric average +- No `condition` — always visible, never conditional + +### 2. Round Config Addition + +New field in `EvaluationConfig` (JSON column, no migration needed): + +```ts +showJurorProgressDashboard: boolean // default false +``` + +Admin toggle in round config to enable/disable the juror progress view. + +### 3. Juror Progress Dashboard + +**Location:** Collapsible card above the project assignment cards on `/jury/competitions/[roundId]`, gated by `showJurorProgressDashboard`. + +**Data source:** New tRPC query `evaluation.getMyProgress(roundId)` returning: + +```ts +{ + total: number, + completed: number, + advanceCounts: { yes: number, no: number }, + submissions: Array<{ + projectId: string, + projectName: string, + submittedAt: Date, + advanceDecision: boolean | null, + criterionScores: Array<{ label: string, value: number }>, + numericAverage: number | null, + }> +} +``` + +**UI:** +- Progress bar: `completed / total` with percentage (shadcn Progress) +- Advance summary: `X YES · Y NO` inline badges +- Submissions table: Project Name | Numeric Average | per-criterion scores | Advance (green YES / red NO badge) | Date — sorted by `submittedAt` DESC, submitted evaluations only + +### 4. Admin Dashboard Changes + +**Summary card** (`AdvancementSummaryCard`): +- Renders on round detail page for EVALUATION rounds when form contains an `advance` criterion +- Donut/bar visual: YES / NO / Pending counts with percentages + +**Assignments table:** +- New "Advance" column after Score column +- Green YES / red NO / gray "—" badges + +### 5. Form Builder Changes + +- New button `+ Advance to Next Round?` alongside existing add buttons +- Disabled with tooltip when one already exists in the form +- Edit mode: `trueLabel`/`falseLabel` customization, description field, `required` locked true, no weight/condition +- Juror rendering: two prominent buttons with green/red color treatment + +### 6. Scope Boundaries + +**In scope:** +- `advance` criterion type (form builder, juror rendering, server validation) +- Juror progress dashboard (gated by round config toggle) +- Admin summary card and table column +- One new tRPC query + +**Out of scope:** +- No changes to `binaryDecision` field or `scoringMode: "binary"` +- No changes to AI summary generation +- No schema migration (all JSON columns) +- Export unchanged (advance values flow through `criterionScoresJson` automatically)