Bigger decks: pick up to 30 activities, built in batches

The create wizard stopped at 15 activities because the API, the prompt and
the salvage path all capped at 18: one reply must be one valid JSON object,
and past ~18 activities models truncate or drop cards. Raising the cap alone
would have shipped decks that came back short.

- The count picker offers 8 / 10 / 12 / 15 / 20 / 30; a deck's "add more" row
  gained +15. The help line says bigger decks take longer.
- /api/generate accepts up to 30 (FREEZMO_DEFAULT_ACTIVITY_COUNT now clamps
  to 30 as well) and sizes its overall deadline from the number of model
  calls instead of a fixed two.
- generateActivities splits anything above 18 evenly across calls (30 → 15 +
  15, 25 → 13 + 12) and merges them into one deck. The first call keeps the
  "add to this deck" contract; later calls are told the title, the types
  already used and the topics already covered. A normalised content signature
  drops a card that repeats an earlier one, so the same idea never ships
  twice. requested/generated still travel in the stream meta.
- phase1-test: a stub Ollama answers two 15-card batches (the second repeats
  one card on purpose) → two calls, the even split, the "already covered"
  prompt, 29 merged cards, the duplicate shipped once, title from the first
  reply, and count 31 answered 400 (59 checks).
- wizard-test: the picker offers 30, the wizard sends count: 30, and the
  30-card deck is stored and opened (99 checks).

Version 0.8.4, SW v106.
This commit is contained in:
Martin Dvořák 2026-10-28 19:11:39 +00:00
commit e3b7bbbd6c
13 changed files with 345 additions and 46 deletions

View file

@ -502,7 +502,7 @@ const en: Record<string, string> = {
"upload.phone.summary": "Ready to freeze",
"upload.phone.summaryDesc": "Check what goes in, then freeze.",
"upload.phone.difficultyHelp": "How deep the questions go.",
"upload.phone.activitiesHelp": "How many activities to build.",
"upload.phone.activitiesHelp": "How many activities to build — bigger decks take longer.",
"upload.phone.folderHelp": "Where the deck lands in your library.",
"upload.nothingAdded": "Nothing added yet",
"upload.summary.files": "Files",
@ -1663,7 +1663,7 @@ const cs: Record<string, string> = {
"upload.phone.summary": "Připraveno ke zmrazení",
"upload.phone.summaryDesc": "Zkontroluj, co se použije, a zmraz.",
"upload.phone.difficultyHelp": "Jak hluboko otázky jdou.",
"upload.phone.activitiesHelp": "Kolik aktivit se vytvoří.",
"upload.phone.activitiesHelp": "Kolik aktivit se vytvoří — větší sady trvají déle.",
"upload.phone.folderHelp": "Kam se sada v knihovně zařadí.",
"upload.nothingAdded": "Zatím nic přidáno",
"upload.summary.files": "Soubory",