1
0

Phase 6: participation grading, gradebook passback, opt-out integrity

Ports the timing-neutral foregone-participation grading scheme from
participation_grades.R: answer quality (per-course level points) minus
a deduction for participation foregone through unavailability,
estimated by Monte Carlo simulation of the actual weighted draw and
averaged over when absences fall, plus a small form-filing incentive
for drawn-while-absent-without-opt-out days. Reason-blind and
luck-protected; zero-answer students floor to 0. Parameters
(allowance in SD units, passing line, form penalty, simulation
size/seed) are course settings. Verified against the R engine's
rendered 2026q2 reports via the new import-legacy command: quality and
availability match exactly, finals within Monte Carlo noise; dropped
students import as inactive enrollments and are excluded identically.

Grades are computed on demand into stored GradeRun snapshots and
reviewed on a grades page with CSV export and per-student reports
(also served to students via a publish toggle). Display scales map
points to UW 4.0, a threshold table (one-click import of the Canvas
course grading scheme), or raw points. Gradebook passback via AGS
sits behind a settings toggle with a review-then-push flow.

Opt-out withdrawals are now soft-deletes with a withdrawn_at audit
trail, and close when class begins (class days gained optional start
times), so availability records cannot be rewritten after the fact.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-31 18:38:22 -07:00
parent 7ec1be5dc6
commit 46f7f55633
27 changed files with 1869 additions and 98 deletions

View File

@@ -103,6 +103,7 @@ configuration: add a custom parameter
pronouns=$com.instructure.Person.pronouns
course_start=$Canvas.course.startAt
course_end=$Canvas.course.endAt
grading_scheme=$com.instructure.Course.gradingScheme
```
The course dates bound the schedule and date pickers; the tool works
@@ -115,6 +116,52 @@ fields). Pronouns appear on the live call card, printed call lists,
and each student's own page. If the account has pronouns disabled,
everything simply shows without them.
## Opt-outs
Students remove themselves from a day's cold-call list by picking the
date on their page; nothing else is asked. There is deliberately no
enforced submission deadline: an instructor running live calls in
class gets up-to-the-second opt-outs automatically, while one who
prints a call list beforehand should just tell students how much lead
time they need (for example, "an hour or two before class"), since
opt-outs after printing won't be on the paper.
Withdrawing an opt-out is bounded, because un-opting-out after the
fact would rewrite a student's availability record (and with it their
participation grade): withdrawal closes when class begins, using the
start time recorded on the schedule page, or at the start of the class
day when no time is recorded. Withdrawals are also recorded rather
than deleted — the opt-out export includes a withdrawn_at column, so
the full history of changes survives.
## Grading
Final participation grades use the timing-neutral foregone-
participation scheme (a port of the earlier participation_grades.R):
a student's grade is the quality of their answers minus a deduction
for participation they missed by being unavailable, estimated by
Monte Carlo simulation of the actual weighted draw and averaged over
when the absences fall, plus a small incentive penalty for being
drawn while absent with no opt-out filed. The reason for an absence
never matters, and luck of the draw never moves a grade. Parameters
(allowance, passing line, penalties, simulation size) are per-course
settings; grades are computed on demand, reviewed on the instructor's
grades page, and shown to students only when the instructor publishes
reports. With gradebook passback enabled, a review-then-push page
sends the reviewed scores to Canvas via the Assignment and Grade
Services; nothing is ever sent without explicit confirmation.
Grades are computed in points out of 100 and displayed through a
per-course scale: the built-in linear UW 4.0 map, a threshold table
(letter grades, importable in one click from the course's own Canvas
grading scheme), or raw points.
The port was verified against the R engine's rendered reports from a
real course: answer quality and availability match exactly; the
simulated penalty agrees within Monte Carlo noise. `flask --app
coldcall_lti import-legacy <dir>` imports a manual-era class directory
for this kind of testing.
## Developing without Canvas
Because a Developer Key takes institutional approval to get, the app