Selected Work - Engineering

BUC Populi - AI-assisted grading & attendance

An internal academic-operations tool for Bethesda University: it pulls student work and class data out of the Populi LMS, drafts essay grades with Claude, and runs a weekly attendance audit that flags F1 international students at immigration-compliance risk - all from a lean Python codebase with a Streamlit dashboard, a handful of CLI scripts, and cron.

GRADING ENGINE· claude-sonnet-4
live
essay_4821.docx
Thesis
18/20
Evidence
16/20
Structure
20/20
Grammar
17/20
86/100
confidence: high
no plagiarismon-topiccitations ✓

DRAFT · pending_review

awaiting human approval · never auto-pushed

Role

Solo Engineer

Stack

Python 3.12 · Populi API v2 · Anthropic Claude · Streamlit · SMTP · cron

Links

GitHub

Timeline

2026

01Overview

BUC Populi automates two of the most time-consuming jobs in running a small university's courses: grading written work and keeping attendance records defensible. It talks to Populi (the university's LMS) over its REST API v2, uses Claude to draft essay grades against a rubric, and uses SMTP to alert professors when a student's attendance record needs attention. There is no database and no custom API backend - Populi is the system of record, and everything else is a script, a dashboard, or a cron job on a single host.

The tool has two pillars:

  1. AI-assisted grading - fetch submissions → extract text → grade against a customizable rubric with Claude → save a draft result. Crucially, no grade is ever pushed back to Populi automatically - every score is held at pending_review for a human to approve.
  2. Attendance-compliance auditing - a weekly multi-course audit that decides, per week, whether a section met online or in person, reconciles that against submissions and attendance marks, and raises SEVIS-compliance flags for international students.

It is deliberately small and sharp: ~3,300 lines of Python, a 4-tab Streamlit dashboard, 6 CLI scripts, a 12-endpoint Populi API client, and a cron schedule - built and maintained by one engineer.

In use across the university, the tool is relied on by ~40 professors, has cut grading time by ~60% versus manual marking, and has largely removed the manual labor of checking weekly attendance for compliance.

AUTOMATION· weekly cron pipeline
live

cron

mon 07:00

fetch

Populi API

grade

Claude

audit

SEVIS

email

SMTP

generate_weekly_report.py
$ cron · mon 07:00
→ fetch_populi  ✓ 12 courses · 326 submissions
→ grade (claude)  ✓ 48 drafts · pending_review
→ audit (sevis)  ⚠ 3 SEVIS flags raised
→ email (smtp)  ✓ 40 professors notified
done in 4.2s
submissions326
graded · draft48
SEVIS flags3
~60%grading time saved

02What I built

  • Grading engine - (grader/engine.py) - builds a structured prompt from a JSON rubric, sends the extracted essay to Claude (claude-sonnet-4-20250514), and returns per-criterion scores, student-facing feedback, flags (plagiarism / off-topic / missing citations), and a confidence level - defensively parsing the model's JSON and never auto-submitting a grade.

  • Attendance-compliance auditor - (populi/attendance_audit.py) - derives online vs. in-person weeks, computes the term week number, detects late submissions, and runs a decision matrix that flags exactly which students need an attendance correction or pose a compliance risk.

  • Streamlit dashboard - (dashboard.py) - a zero-frontend internal web UI with four tabs: Master Report (multi-course audit with a course picker and inline email/schedule controls), Submission & Attendance, Grade Assignments, and Attendance Audit.

  • Email-alert pipeline - (email_alerts.py) - composes per-professor and admin-summary emails from the weekly report JSON and sends them over SMTP.

  • Cron automation - (cron_setup.sh) - a hands-off weekly cadence: generate the report Monday 7:00, email professors 7:30, refresh daily Tue–Fri 8:00.

  • CLI & export utilities - run_grading.py, list_courses.py, export_data.py, submission_report.py, and generate_weekly_report.py for discovery, batch grading, reporting, and CSV/JSON export.

03Architecture

CLI Scripts

run_grading · list_courses · export

Streamlit Dashboard

dashboard.py · 4 tabs

Populi Client

REST client · 45 req/min · pagination · caching

Grading

Claude Sonnet 4 · JSON rubric

Audit

Week logic · SEVIS flags

Email

SMTP · weekly alerts

Data

data/ JSON / CSV · gitignored

A single Populi API client (populi/client.py) is the one door to the LMS; the dashboard and every CLI script go through it. From there the work fans out to three external surfaces - the Claude API for grading, SMTP for alerts, and the local data/ directory (JSON/CSV) for draft grades, the weekly report, exports, and logs. There is no database and no custom API backend: Populi holds the canonical data, and the tool re-derives everything it needs from the API on each run, caching within a session to stay polite to the rate limit.

04Technical challenges

Source-of-truth attendance derivation

Problem
For hybrid sections, whether a given week was online or in person changes what 'present' even means - and guessing from a fixed schedule is wrong the moment a week deviates.
Approach
Read the truth from Populi instead of assuming it. get_week_type() derives ONLINE vs. IN-PERSON from each meeting's is_online field; get_week_num() anchors the term week number to the Monday of the term-start week; and assignment filtering uses a week_end + 1 day cutoff so a Sunday-night submission in a US timezone (early Monday UTC) still counts for the right week.
Result
Week classification that stays correct as real schedules drift, without per-course hand-tuning.

Trustworthy AI grading with a human gate

Problem
An LLM grade that flows straight into a student's record is both academically and ethically unacceptable.
Approach
The grader builds a rubric-driven prompt that demands strict JSON (per-criterion scores, feedback, flags, confidence), parses it defensively (falling back to extracting the JSON object if the model adds preamble), short-circuits empty/too-short submissions, and writes every result as a draft at status: pending_review. Nothing is ever pushed back to Populi automatically.
Result
Claude does the first pass at scale; a human stays the system of record for grades.

Polite API citizenship

Problem
Populi enforces a request-rate limit, and a naive multi-course audit can blow straight through it.
Approach
The client self-throttles to 45 requests/minute (headroom under the 50/min limit), handles pagination transparently, and caches person and term lookups so repeated audits don't re-fetch the same records.
Result
Large multi-course reports run without tripping the rate limit or hammering the LMS.

05Stack & why

Python 3.12 because the job is integration and ops glue - talking to three APIs, parsing documents, and emitting reports - where Python's libraries do the heavy lifting. Populi API v2 is treated as the system of record, so the tool stays stateless and never has to reconcile a second copy of the truth. Claude (Sonnet 4) drafts grades against a rubric because structured, rubric-anchored evaluation is exactly what a strong LLM is good at - behind a human approval gate. Streamlit gives the university a real web dashboard with no frontend to build or host. cron + SMTP turn the whole thing into a hands-off weekly routine, and the local data/ directory (JSON/CSV) is all the persistence a single-operator tool needs.

Python 3.12Populi API v2requestsAnthropic Claudepdfplumberpython-docxStreamlitpandasrichpython-dotenvsmtplibcron

06Outcomes

StatusIn use by BUC staff (internal tool)
~40Professors using the tool
~60%Reduction in grading time vs. manual marking
AttendanceManual weekly attendance-checking effort largely automated
~3,300Lines of Python (single author)
4Streamlit dashboard tabs (Master Report · Submission · Grading · Audit)
6CLI scripts (discovery · grading · reporting · export)
12Populi API v2 endpoints integrated, behind one throttled client
Claude Sonnet 4Rubric-driven essay grading with structured-JSON output
Human-in-the-loopNo grade ever auto-pushed - all drafts held at pending_review
ComplianceAutomated weekly F1 / SEVIS attendance flagging + email alerts
No DB / no APINo database or custom API backend - Populi is the system of record; the tool is CLI scripts, a Streamlit dashboard, and cron on a single host