v4.0.0
A task can now ask for k graders, and when the last required grade lands Panelist compares the weighted scores instead of leaving the decision to whoever reviews first. If the spread stays inside CONSENSUS_TOLERANCE the round is recorded as agreed and the grade closest to the mean becomes the one that will be delivered. If the spread is wider the task moves to the new adjudication status and appears at GET /adjudications with every grade, the spread and the tolerance that was in force, and ordinary reviews on it are refused with 409 until it is decided. POST /adjudications/{task_id} takes the delivered grade and a reason, and needs the new adjudications:write scope, which only the new senior_reviewer role and admins hold; the chosen grade is approved and delivered, and every other grade is recorded as outvoted. Outvoted graders are paid by CONSENSUS_OUTVOTED_PAYOUT, either the full card rate, a CONSENSUS_OUTVOTED_RATE fraction of it, or nothing at all. The delivery export now emits one row per consensus task, the delivered grade, carrying the round status, the grader count and the spread; the suite is 52 tests against PostgreSQL 16.