Crit slot exceptions
Six crit groups (mine, Liuru, among them) each hold a standing weekly slot,
published by the course website’s own api/crit-groups.json. When a public
holiday, a room clash or a tutor swap needs a one-off replacement for a
group’s week, that change today lands as a hand-edited entry in that site’s
exceptions array — a PR against the source of truth for what’s really a
small, recurring coordination problem. This is the slice before that PR: a
board where anyone can propose a replacement slot for a given week, see every
open proposal in one place, and confirm one once it’s settled — live across
every open tab, and still there on reload.
It deliberately doesn’t do more than that. It doesn’t write back to the website’s own data (that stays that repo’s job), and it doesn’t gate who can propose or confirm — the six groups and their tutors are a small, known set, not a public audience that needs authentication.
What good looks like here
- The standing slots and the two exceptions already live on the published site
are real data, fetched from the course API and seeded once at boot
(
src/lib/db.ts) — nothing here is invented to make the demo look populated. - The core promise is persistence: propose an exception, reload, it’s still
there —
spec/exceptions.test.tsasserts this against the running app, the same way the starter’s ownguestbook.test.tsdid before this replaced it. - A proposal that would double-book a room already held by another group’s
confirmed exception (same week, day, time, room) gets a visible warning,
live across tabs and surviving either or both sides later getting confirmed
—
src/lib/clashes.ts, exercised by the clash tests inspec/exceptions.test.ts. - The accessibility floor (
spec/invariants.test.ts) and the read-only/readme/promise (spec/readme.test.ts) are enforced checks, not judgement calls; which system to model, and how thin a slice counts as “wired end to end,” were mine to decide, andCLAUDE.mdrecords the rules that decision produced.