Enumerate every possible sentence, review it, and lock it with a snapshot
"Wir wohnen bei der Schwester. / We live at the sister." was two bugs at
once, and both were the same shape: a template applied to a pairing nobody
had ever read.
Root cause: sentences are built combinatorially (frames x verbs x nouns x
subjects). The space is ~2900 sentences and only a sample had ever been
looked at, so every fix so far has been whack-a-mole on whichever bad one
happened to surface.
The fix is structural, not another special case:
- composeFrame() is now pure, and enumerateCorpus() walks every frame,
verb, noun and case for every consumer (fill-the-article, ein-Woerter,
possessive, Wechsel im Kontext, fused). src/corpus.txt is that full
enumeration, checked in and reviewed.
- Two tests make it foolproof rather than decorative:
* the snapshot test fails if generation drifts from corpus.txt, so no
new sentence can reach a learner unreviewed. Regenerate with
`npm run corpus` and the diff IS the review.
* a coverage test runs the real generators over every sentence level
and asserts each question it produces has a key in the corpus — so
the file is provably the live output, not a parallel implementation.
Two more assert no un-fused contraction and no German leaking into an
English line.
Bugs the audit then found and fixed:
- zu/von/bei + a person means "at/to/from their PLACE". English needs the
-'s ("at the doctor's"), and with a bare definite article German only
allows roles you visit (beim Arzt), not family — "bei der Schwester" is
wrong, "bei meiner Schwester" is right, so family frames are now
possessive-only. Added Aerztin/Lehrerin/Freundin so the role case has a
non-fusing feminine form.
- "zu dem Arzt", "in dem Haus": a fill-the-article sentence may no longer
show a two-word form German obligatorily fuses. Those pairings belong to
the Kontraktionen questions, which already teach them. "zu" therefore
leaves the Dativ lesson entirely, the way "bis" already had.
- mein Mann / meine Frau mean my husband / my wife, not my man / my woman.
- "mein Maedchen" is not idiomatic and was reachable from the possessive
templates; the coverage test caught it.
- You cannot drive into a kitchen, a cellar or a library: the "in" motion
frame is split into drivable places and on-foot-only places.
- "stellt den Stuhl an die Wand" is "against the wall", not "to the wall";
haengen/schreiben/kleben take "on"; wohnen am See is "by the lake".
Also: questions now carry the verb and case they were built from, the
article redraw is depth-bounded so a data mistake degrades to one odd
question instead of hanging, and level 3's advertised prep list matches
what it can actually generate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Uza6mhTpAvSwMQuFc4Cz8
This commit is contained in: