Skip to content

feat(srs): upgrade from SM-2 to FSRS spaced repetition algorithm#58

Open
nymulinfoinlet wants to merge 2 commits intomainfrom
feat/fsrs-algorithm
Open

feat(srs): upgrade from SM-2 to FSRS spaced repetition algorithm#58
nymulinfoinlet wants to merge 2 commits intomainfrom
feat/fsrs-algorithm

Conversation

@nymulinfoinlet
Copy link
Copy Markdown
Contributor

Summary

Closes #45

Replaces the 1987 SM-2 algorithm with FSRS (Free Spaced Repetition Scheduler). Research shows FSRS reduces total reviews by 20-40% while maintaining the same retention rate. FSRS is now the default in Anki (since v23.10) and RemNote.

What changed

  • flashcards.service.ts: Removed calculateSM2(), added FSRS via ts-fsrs library. Legacy SM-2 quality (0-5) is mapped to FSRS Rating (1-4). Legacy cards start as new FSRS cards on first review.
  • Migration 015: Adds stability, difficulty, fsrs_state, lapses columns to flashcards table
  • ReviewFlashcardDto: Updated docstring for both FSRS (1-4) and SM-2 (0-5) input

Note: This branch stacks on PR #57 (Ollama support). Merge #57 first, then this.

Test plan

  • Run migration 015_fsrs_columns.sql
  • Review a flashcard with quality=4 (Good) — verify stability > 0, fsrs_state updates
  • Review with quality=1 (Again) — verify interval resets, lapses increments
  • Legacy SM-2 cards should be treated as new FSRS cards on first review
  • cd backend && npx tsc --noEmit — 0 errors

🤖 Generated with Claude Code

nymulinfoinlet and others added 2 commits April 12, 2026 13:04
Closes #45

Replaces the 1987 SM-2 algorithm with FSRS (Free Spaced Repetition
Scheduler), which research shows reduces total reviews by 20-40%
while maintaining the same retention rate. FSRS is now the default
algorithm in Anki (since v23.10) and RemNote.

Changes:

- flashcards.service.ts: removed calculateSM2(), added FSRS
  integration via ts-fsrs library (MIT, open-spaced-repetition
  project). New methods: mapQualityToFSRSRating() maps legacy
  SM-2 quality (0-5) to FSRS Rating (1-4: Again/Hard/Good/Easy).
  toFSRSCard() reconstructs an FSRS Card from the DB row for
  scheduling. review() now calls fsrs.repeat() instead of SM-2.

- Flashcard interface: added stability, fsrsState, lapses fields
  alongside existing SM-2 fields for backward compat.

- Migration 015_fsrs_columns.sql: adds stability, difficulty,
  fsrs_state, lapses columns to flashcards table.

- ReviewFlashcardDto: docstring updated to explain both FSRS
  (1-4) and legacy SM-2 (0-5) input ranges.

- Legacy SM-2 cards (stability=0, fsrsState=0, repetitions>0)
  are treated as new FSRS cards on first review — FSRS starts
  fresh rather than inheriting the SM-2 schedule, since the two
  algorithms model memory differently.

- package.json: added ts-fsrs ^5.3.2

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(srs): Upgrade from SM-2 to FSRS spaced repetition algorithm

1 participant