Generation guards: cards with repeated wording never ship
A generated Czech literature deck reached a phone with three identical matching definitions — the card could not be solved. The pipeline only deduped matching terms (and ordering items), so repeated definitions and options sailed through. - parseDeck now rejects any card whose options, items, terms or definitions repeat (case-insensitive), through the same drop-or-repair path as the ordering giveaway guard: the card is dropped, or a deck left with too few cards gets one repair round with a clear reason. - The matching dedupe covers definitions too, and both it and the ordering one only trim when the card still meets the schema minimum afterwards — a shorter card would fail validation on the next read and take the whole deck down with it (latent data-loss bug). - The generation prompt states the uniqueness rule. - phase-1 suite: a stub Ollama returns a deck with a repeated-definition matching card (the reported shape), a repeated-option card and a salvageable one; asserts the first two are dropped, the third is trimmed to three pairs and the good cards ship (43 checks). - README: decision 51. Server-side only (lib/ai.ts, lib/prompts.ts) — no client bundle change, no SW bump.
This commit is contained in:
parent
37a84df462
commit
f202653017
4 changed files with 177 additions and 22 deletions
17
README.md
17
README.md
|
|
@ -1346,8 +1346,21 @@ Things I chose while building, with the reasoning:
|
|||
(`classifyOllamaFailure`) and mapped to `usage_limit` / `throttled` kinds — the client renders
|
||||
the same localized message in every model flow, with a jump to the key field and a link to
|
||||
Ollama, and keeps the user's input so Retry works right after swapping the key. Verified by the
|
||||
phase-1 suite (38 checks, including the real route mapping against a stub Ollama returning a
|
||||
monthly-limit body, and a two-device sync round-trip).
|
||||
phase-1 suite (43 checks, including the real route mapping against a stub Ollama returning a
|
||||
monthly-limit body, a two-device sync round-trip, and the generation guards below).
|
||||
|
||||
51. **Cards with repeated wording never ship.** The model sometimes pads a matching card with one
|
||||
definition copied across several terms (a Czech literature deck arrived on a phone with three
|
||||
identical definitions, so the card could not be solved by knowing the material), or repeats an
|
||||
option. The generation pipeline now rejects any card whose options, items, terms or definitions
|
||||
repeat (case-insensitive) — the same drop-or-repair path the ordering giveaway guard already
|
||||
used, so a deck with too few cards left over gets one repair round instead. The matching and
|
||||
ordering dedupe only trims a card when it still meets the schema's minimum afterwards: a
|
||||
shorter card would fail validation on the next read and take the whole deck down with it, so
|
||||
below the minimum the original is kept and the card is rejected instead. The generation prompt
|
||||
states the uniqueness rule too. Verified by the phase-1 suite's stub-Ollama generation: the
|
||||
repeated-definition card is dropped, a salvageable card is trimmed to three pairs, the
|
||||
repeated-option card is dropped and the good cards still ship.
|
||||
|
||||
41. **The learning log is an event log, so it lives in IndexedDB.** Decks and homework stay in
|
||||
`localStorage` (small, always loaded), but answers + SRS schedules go to a versioned
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue