| name | fluent-review |
| description | Run today's spaced-repetition review queue — items scheduled by SM-2 that need reinforcement before the learner forgets them. Triggered only when the learner types /fluent-review. Pulls due items from spaced-repetition.review_queue.today, generates a targeted exercise for each, evaluates the response, updates SM-2 parameters, and reshelves items into the correct future queue. |
| allowed-tools | Read, Write, Bash |
| disable-model-invocation | true |
Spaced-Repetition Review Session
Overview
Replay items the learner learned before, timed so they hit just before the forgetting curve drops them. This is the single most effective session type — the system depends on it running daily. Items the learner gets right get pushed further into the future; items they miss come back tomorrow.
When to Use
Trigger this skill only when the learner types /fluent-review. The skill is gated with disable-model-invocation: true — mutating SM-2 state from a misread prompt would cascade through every future session.
Skip this skill when the queue is empty — suggest /fluent-vocab or /fluent-learn instead.
Instructions
1. Load review queue
python3 "${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PROJECT_DIR:-.}}/.claude/hooks/read-db.py"
Read spaced-repetition.review_queue.today and daily_limits.review_items_per_day. Sort items by priority (critical → high → medium → low). Cap at the daily limit (usually 20).
If the queue is empty:
🎉 No reviews due today! Your spaced repetition is up to date.
Want to practice something new? Try:
- `/fluent-learn` — adaptive mixed practice
- `/fluent-vocab` — learn new words
- `/fluent-progress` — see your stats
2. Opening
# 🔄 Today's Spaced Repetition Review
Hallo {name}! Time to review items your brain is about to forget. This keeps everything fresh. 🧠
**Items Due Today:** {count}
**Estimated Time:** ~{minutes} min
Why review? Spaced repetition prevents forgetting, moves items into long-term memory, and builds automaticity.
**Ready? Let's start!** 💪
3. Generate exercise per item
Each item has:
{
"item_id": "...",
"item_type": "error_pattern | vocabulary | grammar_rule",
"easiness_factor": 2.5,
"interval_days": 6,
"repetitions": 2,
"due_date": "YYYY-MM-DD",
"priority": "critical | high | medium | low",
"content": "...",
"answer": "..."
}
Generate an exercise matched to item_type:
- error_pattern: load the pattern from
mistakes-db, create a scenario that forces the correct form. E.g. formal_informal_confusion → ask the learner to complete a formal email opening.
- vocabulary: recognition (target_language → explanation_language), production (explanation_language → target_language), or cloze — rotate modes. Use
preferences.explanation_language, not native_language — they can differ (e.g. an immersion learner sets explanation_language to the target language itself). If explanation_language == target_language, skip the translation directions entirely and drill with a target-language-only synonym/definition/cloze instead.
- grammar_rule: a fill-in or error-correction exercise that tests the rule.
Present one at a time:
## Review {N}/{total} — {priority emoji}
**Type:** {item_type}
**Last reviewed:** {X} days ago
**Current mastery:** {stars}
{exercise}
**Type your answer:**
4. Evaluate + update SM-2
Use the fluent-feedback-formatter skill for per-answer feedback.
Then stage the item for the end-of-session update. Do NOT hand-edit spaced-repetition.json — use review_results[] in the fluent-db-updater payload:
{ "item_id": "vocab_huis", "quality": 4 }
The update-db.py script runs the SM-2 math (see fluent-sm2-calculator skill) and rebuilds the queue. Mapping: quality = floor(score / 2).
5. Progress pulse every 5 items
## Progress Update
**Reviewed:** {N}/{total}
**Accuracy:** {percent}%
**Time Remaining:** ~{min} min
Keep going! 💪
6. Session summary
## 🎉 Review Session Complete!
**Reviewed:** {count}
**Accuracy:** {percent}%
**Time:** {min} min
### Breakdown
**Mastered (no mistakes):** {count} — won't appear again for a while 🎉
**Good (minor slips):** {count} — next in {X} days
**Need more practice:** {count} — tomorrow again
### Next Review Schedule
- Tomorrow: {count}
- This week: {count}
- Next week: {count}
**Streak:** 🔥 {X} {day/days} 🔥
**Tip:** {one line of advice based on accuracy}
{target-language well done}! 🌟
7. Update all databases
Use the fluent-db-updater skill — don't guess the payload shape from memory,
check fluent-db-updater/SKILL.md (or its
.claude/references/db-updater-payload.example.json) for the exact fields
update-db.py expects. Two field-name mistakes are easy to make and both
corrupt data silently instead of erroring:
skill_scores is { "<skill>": { "exercises": N, "correct": N, "time_minutes": N } } per skill — not {"correct": N, "incorrect": N}. The script derives incorrect/accuracy from exercises - correct, so a
payload with no exercises field produces negative incorrect-counts and
accuracy over 100% without any validation error. correct = count of
correct exercises, not a percentage.
- The free-text summary field is
session_notes, not notes.
errors[].your_answer / errors[].correct_answer (not incorrect/correct).
Also include:
command_used: "/fluent-review", skills_practiced: [derived from reviewed items]
review_results[] — every item reviewed, with quality
errors[] — only patterns where the learner got it wrong (bumps frequency)
focus_next_session[] — the 2-3 items with lowest quality this session
If a bad payload does slip through and corrupts progress-db.json /
mastery-db.json / session-log.json (e.g. negative incorrect_count,
accuracy > 1.0, exercises_completed not matching the items reviewed):
restore all 6 files from .backups/pre-update-<session_id>/ (written
automatically before the write) and resubmit a corrected payload with the
same session_id — duplicates are otherwise rejected, so the restore is
required before a resend.
Save exchange to /results/fluent-review-session-{NNN}.md for later analysis.
Examples
Example 1 — vocabulary review with wrong answer
Review 3/12 — 🔴
Type: vocabulary
Last reviewed: 6 days ago
Current mastery: ⭐⭐⭐☆☆
Dutch: het raam
What does it mean in English?
Learner: "the door"
❌ Close — those are both openings in a wall, but not the same.
Corrections:
- 🟡 "the door" → "the window" (vocabulary —
het raam is window; de deur is door)
Correct version:
"het raam" = the window.
Score: 3/10 💪 Easy to mix — we'll review this again soon.
(Logged: review_results[] item quality=1 → interval_days=1, repetitions=0, stays in today's queue.)
Example 2 — correct answer with mastery bump
Review 7/12 — 🟡
Type: grammar_rule
Last reviewed: 14 days ago
Current mastery: ⭐⭐⭐⭐☆
Complete: "Ik schrijf u omdat ik ____ kan komen." (reason: can't come)
Learner: "niet"
✅ Perfect — omdat-clause word order locked in.
Answer: "Ik schrijf u omdat ik niet kan komen."
Score: 10/10 🎯
(Logged: quality=5 → interval_days = round(14 * EF), queue: later. consecutive_correct = 5, mastery → 5 ⭐⭐⭐⭐⭐.)
Critical Rules
- Daily. The whole system assumes the learner runs
/fluent-review every day. Missing a day breaks the intended spacing.
- Never auto-invoke. Gated; must fire only on explicit
/fluent-review. Long interactive + SM-2 mutation.
- One item at a time. Rushing = false positives.
- Let the learner struggle. If they don't remember, that's useful data (quality 0-2). The algorithm needs honest signals.
- Never hand-edit
spaced-repetition.json. Queue is rebuilt on every update-db.py call.
What the Schedule Means
Tell the learner if they ask:
- 1 day — new or struggling items
- 2-3 days — learning, building strength
- 1 week — getting comfortable
- 2+ weeks — strong, maintenance only
- 1+ month — mastered, long-term memory