The problem
High-school students and parents need to judge which admission tracks to apply for, using university requirement data and AI analysis.
Decisions
- PDFs are parsed from their text layer (pdftotext -layout, word coordinates for large documents) instead of vision: 93% complete records on the same documents, at zero cost.
- Two layers, so no number appears without evidence: AI fit (strong / medium / weak) by default, while statistical admission probability stays behind a feature flag until real admission data exists.
- The academic year comes from one stored value with a three-step fallback instead of a formula. The formula asked for a year that didn’t exist yet each January — and the tests copied the same formula.
What broke — and the fix
- Figures like “27 samples · 22%” appeared live, from a feature still running on demo random data. The sample-sufficiency check now sits on the one path every screen shares, so a single guard covers them all.
- Fifty-five department pages with Korean IDs rendered blank: path values reached server components still URL-encoded. An ID-normalization module and 9 regression tests fixed it.
Directing the AI
Sub-agent self-reports weren’t trusted: row and column totals were recomputed centrally, catching 22 aggregation errors. After an AI answer misquoted a grade sum (computed 7, written 5), numbers were limited to values from a deterministic judge.
Results
- 980 tests in 90 files passing — identical on two runs of the same commit
- Matching response 2,068 ms → 1,033 ms
- 55 blank department pages restored; coverage at one university 39% → 98%
- 22 data-integrity errors blocked before release
- 4,173 rows of admissions data; cached AI fit in 0.78 s with 0 tokens