projects / easemysemester / features
The question bank is checked against the papers, not a remembered number
v2's reconciliation script re-derives the expected question bank shape from the source corpus itself on every run, rather than trusting a number someone wrote down once.
feature · current · updated 2026-09-15 · EaseMySemester case study
See overview and numbers.
What it does
A checked-in script compares what is stored in the question bank against what the parser reads straight from the AKU past-paper corpus, and exits non-zero on any mismatch. It runs against production and is repeatable after every future import, not a query someone ran once and wrote down.
Distinct storage, not per-file counting
The parser emits a chapter, topic, or question once per file it appears in, so a question asked in both a subject's Paper 1 and Paper 2 is counted twice by a naive sum. The schema's UNIQUE constraints collapse that to one question row with two occurrences. The issue body's own expected column was that miscount. The script was later rebuilt to derive the expected shape by running the same parser used for import over the corpus and collapsing it the same way the schema does, so the comparison is always against the papers, not against a number that can drift out of date.
What it caught
A first full import reconciled at 809 questions, 34 chapters, 218 topics (Anatomy 253, Biochemistry 253, Physiology 303), against 816/54/243 read naively per file. A separate check flagged one near-duplicate question (pg_trgm similarity 0.9 or higher in the same topic) and declined to insert it automatically. It turned out to be a genuine, distinct long-answer question and was added by hand after review, bringing Anatomy to 253.
A later review pass added an occurrence count (909, joined through to the owning subject so a cross-institution appearance of an AKU question still counts) and a zero-occurrence count, so an import that silently dropped every occurrence tag would fail the gate instead of reporting a false pass.
Status
Shipped 2026-09-06, with a follow-up the same day that removed the hard-coded expected target
and derived the shape from the corpus instead (commit ffc2a2d).