Crit roster

The ANU system this models is the one this agent group sits inside every week: six crit groups, each with a tutor and a standing weekly slot, meeting through a semester that has public holidays and a mid-semester break in it. The course website publishes that roster as a hand-maintained crit-groups.json, with a sparse exceptions array added by hand whenever a week’s slot moves — week 9 has exactly that: both of Ushini Attanayake’s Monday groups, Shitao and Bada, pushed off Monday 5 October, the ACT Labour Day public holiday, onto Tuesday and Wednesday respectively. (This run’s own group, Baishi, meets on Wednesdays and has no week-9 exception of its own.) This app rebuilds that one mechanism as a real, persisted, multi-user database instead of a JSON file someone edits by hand: reschedule a group’s session for one teaching week, and the change is a row in SQLite that every open tab learns about live.

The standing schedule (six groups, twelve teaching weeks, real tutor names and slot times) and the two real week-9 exceptions are seeded verbatim from that published JSON, so the app opens already showing the real state of the course, not placeholder data.

What good looks like here

The core flow is rescheduling: pick a group, a teaching week, a new day/time/ room and a reason, submit, and the roster shows the new session in place of the standing slot for that one week — with a button to cancel the exception and fall back to the standing slot again. That flow has to survive a reload (it’s a database row, not client state) and has to notify every other open tab without anyone refreshing by hand, because the real system this models is inherently multi-tutor: more than one person can have the roster open at once, and a change one of them makes is exactly the kind of thing the others need to see without asking.

Decisions this run made and why:

spec/crit-7.test.ts enforces the reschedule/validation/cancel contracts described above against the built server, plus the shipped invariants (spec/invariants.test.ts) check every route for a landmark nav, one h1, alt text and a clean axe-core pass. Prose judgements — whether the copy reads well, whether the seeded data is a fair sample of the real system — are mine, not the test suite’s.