Learn Review
Reviews facts in workspace/learning/facts/ whose next_review date is today or in the past. Applies SM-2 grading and rewrites frontmatter in-place. Records every grade in workspace/learning/.state/review-log.jsonl.
SM-2 Formula (implement exactly as specified)
Given current reps, interval, ease, lapses:
Again (grade 0):
reps = 0interval = 1ease = max(1.3, ease - 0.2)(round to 2 decimal places)lapses = lapses + 1
Hard (grade 3):
interval = round(interval * 1.2)(minimum 1)ease = max(1.3, ease - 0.15)(round to 2 decimal places)reps = reps + 1
Good (grade 4):
- If
reps == 0:interval = 1 - Else if
reps == 1:interval = 6 - Else:
interval = round(interval * ease)(minimum 1) easeis unchangedreps = reps + 1
Easy (grade 5):
- Same interval as Good, then additionally:
interval = round(interval * 1.3)(minimum 1) ease = ease + 0.15(round to 2 decimal places)reps = reps + 1
For all grades: next_review = review_date + interval days
Ease floor: 1.3. Never let ease drop below 1.3 regardless of how many Again grades.
Workflow
Step 1 — Scan for due facts
- Read all
.mdfiles inworkspace/learning/facts/ - Parse the frontmatter of each file
- Get today's date (YYYY-MM-DD)
- Select facts where
next_review <= today - Sort by
next_reviewascending (oldest due first) - Take up to 5 facts (N=5 default)
If no facts are due:
"Nenhum fato vencido hoje. 🎉 Próxima revisão: {earliest next_review across all facts}." Stop here.
If workspace/learning/facts/ does not exist or is empty:
"Nenhum fato encontrado. Use /learn-capture para adicionar fatos primeiro." Stop here.
Step 2 — Review loop (one fact at a time)
For each due fact (up to 5):
2a. Show the question:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📚 Deck: {deck} | Fato {current}/{total_due_shown}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
❓ {Retrieval Q content}
[Pense na resposta antes de prosseguir. Pressione Enter quando pronto.]
Wait for the user to confirm they've thought about it (any input is fine).
2b. Show the answer:
✅ Resposta:
{Fact content}
💡 Por quê importa:
{Why it matters content}
2c. Ask for grade:
Como foi?
0 - Again (errei / não lembrei)
3 - Hard (lembrei com dificuldade)
4 - Good (lembrei bem)
5 - Easy (muito fácil)
Wait for the user to enter 0, 3, 4, or 5. Accept also the words "again", "hard", "good", "easy" (case-insensitive).
Step 3 — Apply SM-2 and update file
For the grade received:
- Compute
prev_interval = current interval - Compute
prev_ease = current ease - Apply SM-2 formula above to get
new_interval,new_ease,new_reps,new_lapses - Compute
new_next_review = today + new_interval days - Rewrite the fact file with updated frontmatter, preserving the body content exactly
Frontmatter rewrite rules:
- Update only:
next_review,interval,ease,reps,lapses - Preserve all other fields unchanged:
id,source,deck,created - Preserve the body (everything after the closing
---) exactly as-is
Step 4 — Append to review log
Append one JSON line to workspace/learning/.state/review-log.jsonl (create file if it doesn't exist, create directory if needed):
{"ts": "{ISO8601_timestamp}", "fact_id": "{id}", "grade": "{again|hard|good|easy}", "prev_interval": {N}, "new_interval": {M}, "prev_ease": {X}, "new_ease": {Y}}
Grade string mapping: 0→"again", 3→"hard", 4→"good", 5→"easy"
Step 5 — Next fact
Continue with the next due fact. After all N facts (or all due facts if < N):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Sessão de revisão concluída!
Revisados: {N} fatos
Resultado: {X} Good/Easy | {Y} Hard | {Z} Again
Próxima revisão: {earliest next_review across all facts}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Verification helper (Grade Good progression)
When testing, the interval sequence for repeated Good grades starting from reps=0, interval=1, ease=2.5:
| Review | Grade | reps before | interval before | → reps after | → interval after |
|---|---|---|---|---|---|
| 1st | Good | 0 | 1 | 1 | 1 |
| 2nd | Good | 1 | 1 | 2 | 6 |
| 3rd | Good | 2 | 6 | 3 | 15 (round(6*2.5)) |
Constraints
- Max N=5 facts per session. If more are due, the user can run again.
- ONLY update files in
workspace/learning/facts/andworkspace/learning/.state/review-log.jsonl. - Do NOT modify
deckmetadata files or any file outside these two locations. - Do NOT skip the log write — even if the user types a grade quickly, always append to the log.
- If a fact file cannot be read (corrupted frontmatter), skip it and report: "⚠ Fato {filename} ignorado — frontmatter inválido."