{"id":15102,"plugin_id":"plugin_asdk_app_6aa049955f488191aea7a65248d0b8dd","kind":"skill","collection_source":null,"comparison_source":null,"observed_at":"2026-09-30T23:10:48.716Z","digest":"18ba9612a4be2dbd71da903ddad1e611980f0d14f84e6d651e5e9070ac748086","against":null,"payload":{"name":"generate-quiz","description":"Build a daily vocabulary quiz for a Gordito learner from the words their spaced-repetition schedule says are due, using what you already know about them.","included_files":[],"skill_md_contents":"---\nname: generate-quiz\ndescription: Build a daily vocabulary quiz for a Gordito learner from the words their spaced-repetition schedule says are due, using what you already know about them.\n---\n\n# Generate a quiz from due vocabulary\n\nGordito stores the record; you supply the judgement. The server decides **when** a word\ncomes back and you decide **what the question looks like**. Never invent a review\nschedule, and never quiz a word the server did not return as due.\n\n## The loop\n\n1. `get_enrollments` — pick the enrollment. If there is none, the learner has not finished\n   signing up: send them to the sign-up page to choose their language. You cannot create an\n   enrollment yourself, and you should not try.\n2. `get_vocabulary` with `dueOnly: true` — this is the entire pool of words you may quiz.\n   If it returns nothing, say so and stop; do not invent words to pad a session.\n3. `generate_quiz` — each question naming the `vocabularyIds` it tests.\n4. Wait. The learner answers in the card and it submits for you.\n5. `grade_questions` — one call for the whole quiz, scoring every word each question\n   tested, honestly.\n\n## Writing the questions\n\nWrite the prompt in the learner's **origin** language and ask them to produce the\n**learning** language. Production is the point: recognition is what they can already do.\n\n**Draw on what you know about them.** This is the reason Gordito is worth using instead\nof a flashcard app. If they have been talking to you about Formula 1 all week, set the\nsentence at a race. If they mentioned their in-laws are visiting, use that. A word met in\na sentence that matters to the learner is a word that sticks.\n\nVary the shape across a session so it does not read as a drill:\n\n- **Translate a sentence** — the default. Embed the due word in a natural sentence.\n- **Complete the gap** — give a sentence in the learning language with the word removed.\n- **Answer a question** — ask something whose natural answer needs the word.\n\nRules that matter:\n\n- **Name every due word the question tests** in `vocabularyIds`. A question without any is\n  rejected: the review would not count and the word would stay due forever. One word per\n  question is the usual shape and the easiest to grade honestly, but a sentence that genuinely\n  exercises two due words may name both — each is scored separately afterwards, so you are not\n  forced to average them. Never list a word the prompt does not actually test just because it\n  is due.\n- **Never put the answer in the prompt.** Do not write the learning-language word, and\n  avoid a cognate so transparent that no recall is needed.\n- **Keep prompts to one sentence.** You are testing one word, not reading comprehension.\n- **Use the example sentence as a hint of register**, not as the prompt itself — quizzing\n  the sentence they were taught tests memory of the card, not knowledge of the word.\n- **Cap a session at 10–15 questions** even when more is due. A session someone finishes\n  beats one they abandon; the rest stays due tomorrow.\n\n## Grading\n\nScore on the FSRS rating scale, and be strict — this feeds the scheduler directly:\n\n| Score | Meaning |\n| --- | --- |\n| 1 Again | Wrong, blank, or the wrong word entirely. **Requires at least one recorded error.** |\n| 2 Hard | Right, but laboured, hesitant, or awkwardly phrased. |\n| 3 Good | Right. |\n| 4 Easy | Right, immediate, and idiomatic. |\n\nA generous grade is not kindness. Marking a shaky answer `3` tells the scheduler the\nlearner knows that word, and they will stop seeing it precisely when they most need to.\nIf the answer would not pass with a native speaker, it is not a 3.\n\n**Mark the whole quiz in one call.** `grade_questions` takes every question you are\nmarking. The batch is written together or not at all, so if one grading is rejected nothing\nlands — you fix it and resend, rather than discovering half the quiz is marked and half is not.\n\n**Write the marking in the language being learned.** `correctionNote` and every error `rule`\ngo in the enrollment's learningLanguage, not in the learner's own language and not in English.\nReading the explanation is itself practice. Keep it short enough that a B1 learner gets it\nfirst time — a plain sentence beats a precise one they have to decode.\n\n**Score each word on its own evidence.** A question that tested two words takes two scores.\nIf the sentence got `manzana` wrong and `pan` right, that is a 1 and a 4, not a 2 for both.\nAveraging is the one thing the split model exists to prevent.\n\n**A blank answer is a 1, never skipped.** The question was tied to words the learner was\nmeant to produce; not producing them is not producing them. Grade it, record an error saying\nnothing was written, and let the scheduler hear it.\n\nWhen you record an error, reuse an existing `errorType` whenever the mistake is the same\nkind — `noun_gender` twice is a pattern the learner can be shown, while `noun_gender` and\n`wrong_gender` are two things that look rare. Snake_case, specific, and about the\n*grammar*, not the word: `ser_vs_estar`, `subjunctive_after_doubt`, `preterite_vs_imperfect`.\n\n### Quote the mistake, do not describe it\n\nEvery error carries `originalForm`: the exact text from the learner's answer that was wrong,\ncopied character for character. The app finds that text and strikes it in place, writing\n`correctedForm` above it. This is the whole reason the learner can see where they went wrong,\nso it has to match.\n\n- **Copy, do not retype.** `originalForm` must appear verbatim in the response. Same accents,\n  same spacing, same case. If it does not match, the mark cannot be drawn.\n- **A missing word is a widened span, not an empty one.** For `\"voy playa\"` where the answer\n  should be `\"voy a la playa\"`, quote `\"voy playa\"` → `\"voy a la playa\"`. Never quote `\"\"`.\n- **A spurious word is an empty correction.** For `\"yo yo voy\"`, quote `\"yo \"` → `\"\"`.\n- **Quote the smallest span that carries the mistake.** `\"el manzana\"` → `\"la manzana\"`, not\n  the whole sentence. Two errors in one answer are two spans.\n- **Do not overlap two spans.** Only the first is drawn; the second is listed separately.\n- **Set `occurrence`** when the text you quoted appears more than once. `0` is the first.\n\n`correctionNote` is for the one-line explanation — *\"manzana is feminine\"* — not for restating\nthe sentence. The marked-up sentence is drawn from the errors.\n\n### Vocabulary you meet while marking\n\nGrading is when a gap is most visible. If the answer reveals a word the learner clearly does\nnot have, pass it in `addVocabulary` and it joins the notebook, linked to the error that\nexposed it. Check `get_vocabulary` first — an exact pair already saved is skipped and reported\nback rather than duplicated, but a near-duplicate (`manzana` against `la manzana`) is not\ncaught for you. Add the word the learner would actually look up.\n\nAccepted spelling variants, regional forms, and missing accents are judgement calls.\nA missing accent that changes the word (`papa` / `papá`) is an error; one that does not\nis worth a `2` with a note, not a `1`.\n\n## After the session\n\nSay what happened in one or two sentences: how many were right, and the one pattern worth\nnoticing. If the same `errorType` came up more than once, name it and offer to drill it\ntomorrow. Do not list every answer back — they just did the quiz.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}