Inspiration

A quiz reports a score. A score can't tell a teacher what to do on Monday. Two students pick the same wrong answer for opposite reasons: one thinks moving objects need a constant push, the other thinks the throw is stored in the ball. Same red cross, opposite faults, opposite fixes. Every adaptive platform personalises difficulty. Almost none personalise the diagnosis.

What it does

Faultline names the exact misconception behind a wrong answer, one of twenty fault lines in mechanics, and teaches only that. It asks adaptively, so no two students see the same sequence. Students explain their reasoning in their own words, which separates faults that produce identical wrong answers. The output is a misconception map: every fault line marked confirmed, suspected, ruled out, or not yet probed. It says "not sure yet" when the diagnosis isn't separated. With an Evorozen Neural Pulse key, profiles persist, so a fault found in September is still on the map in October.

How we built it

The engine is Bayesian, not a chatbot. One probability per fault line, updated in log-odds. The next question is chosen by expected information gain plus a coverage term, so no fault goes unasked. Stopping is arithmetic, not patience: a fault needs 82% belief and a 25-point lead, and the map never closes while a remaining question could overturn the answer.

The AI layer does two jobs, neither of them physics. Neural Pulse reads the student's words and returns signed evidence, never a verdict, and rewrites the authored lesson in the student's voice. Its virtual database replaces a backend entirely. Every model output is gated in code, not prompted: unknown fault ids are dropped, weights are clamped, lessons pass through verbatim, and every call falls back to an offline path. With no key, the whole app still runs.

npm run verify runs lint, typecheck, 79 tests, and a build. A Playwright smoke test drives a real browser, because a Next.js page can look finished with no handlers attached. That is exactly how our start screen once shipped dead.

Challenges we ran into

Information gain alone never picked the single-fault items, so some faults sat unasked. We added the coverage term. Our first response model made the correct answer most likely for every student, so nothing looked informative; centring evidence against the base rate fixed it, and the test that caught it is now a permanent invariant. A page that hydrates nothing taught us to smoke test in a real browser. Any key inlined in a public bundle is readable by anyone, so the key is supplied at runtime and never leaves the student's browser.

Accomplishments that we're proud of

All twenty fault lines are reachable, and a test proves it by simulating a student who holds each one. Honesty is enforced in code: the engine cannot announce a diagnosis while a remaining question could change it. 79 tests, 3 runtime dependencies, zero backend. Every fault entry explains why the intuition is reasonable, and a test asserts no entry ever calls the student careless.

What we learned

The hard part wasn't the math, it was what the math silently excluded. Both worst bugs were ranking holes, caught only by adversarial tests. Gate AI in code: a prompt is a request, a clamp is a guarantee. And the honest failure mode, "not separated yet", earned more trust than a confident answer ever did.

What's next for FaultLine

A teacher cohort view showing which faults are common this week. More domains: the engine is generic, the fault bank is data, so chemistry and fractions are next. Longitudinal replay after instruction, showing which fault lines actually moved. Classroom mode as a pre-test that outputs lessons instead of scores.

Share this project:

Updates

Submission history