User guide
Results and exports
Each grading run is a session, saved under results/<session_id>/. The session id is the assignment id plus a timestamp, for example hw1_20261006_142233.
Session directory#
results/<session_id>/
├── grades.csv student_id, score, execution status, review flags
├── grading_session.json full state; reload it from the Overview page
├── summary.json class summary
├── flagged_submissions.csv the review queue
├── class_report.md the class overview as markdown
├── feedback/<student>.md student-facing feedback
├── executed_notebooks/ probe cells stripped
└── raw_results/<student>.json rubric-level detail with evidence
The probe cells are removed from executed notebooks before they are saved, so nothing in results/ reveals the hidden tests.
Result schema#
Each raw_results/<student>.json is a serialised SubmissionResult:
{
"student_id": "student_003",
"status": "graded", // pending | graded | error | skipped
"needs_review": true,
"total_score": 71.5,
"automatic_total": 71.5,
"max_score": 100.0,
"confidence": 0.75, // lowest item confidence
"review_reasons": ["Center City split correctly: lost 7.5 of 15"],
"discovery_warnings": [],
"execution": {
"success": true, "attempted": true, "timeout": false,
"execution_time_seconds": 8.4, "mode": "docker",
"error_cell": null, "error_message": null
},
"items": [
{
"rubric_id": "center_city_split",
"name": "Center City split correctly",
"type": "deterministic",
"points_possible": 15.0,
"automatic_score": 7.5,
"final_score": 7.5,
"status": "partial",
"confidence": 0.75,
"feedback": "...",
"evidence": { "...": "..." },
"manual_override": false,
"manual_score": null,
"override_reason": ""
}
]
}
The values above are illustrative. Every item keeps both automatic_score and final_score, so a manual override never destroys the automated result.
Exports#
The Export page offers these downloads, all built by GradingSession:
| Download | Method | Contents |
|---|---|---|
| Grades CSV | grades_csv() | One row per student: student_id, display_name, total_score, max_score, percentage, letter, execution_status, manual_review, reviewed, manual_override, confidence |
| Rubric CSV | rubric_csv() | One row per student per rubric item |
| Flagged CSV | flagged_csv() | The review queue |
| Feedback ZIP | feedback_zip() | Every feedback/<student>.md |
| Session archive | archive_zip() | The whole session directory |
Reloading and regrading#
A saved session can be reloaded from the Overview page, or in Python:
from grader.results import GradingSession, list_sessions
for entry in list_sessions():
print(entry["session_id"], entry["assignment_name"], entry["submissions"])
session = GradingSession.load("results/hw1_20261006_142233")
session.set_override("student_003", "center_city_split", 15,
reason="Alternative valid implementation.")
session.mark_reviewed("student_003")
session.save()
Regrading (after a rubric fix, for example) regenerates every automatic score. With overrides preserved, your decisions are put back on top:
service.regrade(session, candidates, preserve_overrides=True)