Well yeah, we just do in person assignments. We keep one every week, not necessarily a new topic every week, the difficulty is distributed, and take best K of N, which automatically allows for absentees and such. The system works well overall. For very weak students (bottom 10%ish) we customize it a bit and make a curriculum of sorts, sometimes re-covering content from a few weeks ago (AI is very useful for analysing answer transcripts and finding these weak points). And then, a final, also in person, for like 15% of the grade.
Large programming assignments also work decent (for now at least), where codex is encouraged, but we make the assignment research oriented and obscenely large with lots of messy and dependent steps, enough that you have to steer enough to do context management and not output slop reports/inferences. It is almost like a research project, where AI's "taste" is still extremely lacking (we often see totally circular/trivial-but-dressed-up investigative results from sloppers, very much like the slop neurips/iclr papers these days). Just one of these per course with a 10 minute in person viva at the end. Previously this used to be a project part of the course, but the old way with reports and presentations just ended up with way too much slop to use as a signal. Also, we just made it individual instead of a group project.
For this type of course, grading on a curve also made less sense, so we instead do a kind of "cluster" based grading. We start from the top giving S, see where the first big gap is, that starts A, the next big gap starts B, and so on. These clusters form really well in the above type of courses (empirically, undergrad lin alg, undergrad databases, and grad RL courses) and matches in-class judgement.