From ef21890c6e1392cb3c5131534834f0f9d2456d4b Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 02:49:16 +0800 Subject: [PATCH 1/7] Enable FSRS by default Make FSRS (Free Spaced Repetition Scheduler) enabled by default for new users and users who haven't explicitly configured it. Changes: - Add BoolKey::Fsrs to default-true boolean keys in Rust backend - Set defaultValue to true for FSRS toggle in deck options UI --- rslib/src/config/bool.rs | 1 + ts/routes/deck-options/FsrsOptionsOuter.svelte | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/rslib/src/config/bool.rs b/rslib/src/config/bool.rs index c76787cb0..d9bd31b8a 100644 --- a/rslib/src/config/bool.rs +++ b/rslib/src/config/bool.rs @@ -79,6 +79,7 @@ impl Collection { | BoolKey::RestorePositionReviewer | BoolKey::LoadBalancerEnabled | BoolKey::FsrsHealthCheck + | BoolKey::Fsrs | BoolKey::NormalizeNoteText => self.get_config_optional(key).unwrap_or(true), // other options default to false diff --git a/ts/routes/deck-options/FsrsOptionsOuter.svelte b/ts/routes/deck-options/FsrsOptionsOuter.svelte index 49d4c681d..d7cd5f2d4 100644 --- a/ts/routes/deck-options/FsrsOptionsOuter.svelte +++ b/ts/routes/deck-options/FsrsOptionsOuter.svelte @@ -96,7 +96,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html /> - + openHelpModal(Object.keys(settings).indexOf("fsrs"))} From da9dd4b315655e1062bed31c8ec6c74e62e42113 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 03:02:51 +0800 Subject: [PATCH 2/7] Fix test for FSRS default enabled Update deckconfig::update::test::updating to use actual config values from get_deck_configs_for_update() instead of hardcoded values. This ensures the test works correctly now that FSRS is enabled by default. --- rslib/src/deckconfig/update.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rslib/src/deckconfig/update.rs b/rslib/src/deckconfig/update.rs index a9a27753e..0ac412d5d 100644 --- a/rslib/src/deckconfig/update.rs +++ b/rslib/src/deckconfig/update.rs @@ -501,7 +501,7 @@ mod test { limits: Limits::default(), new_cards_ignore_review_limit: false, apply_all_parent_limits: false, - fsrs: false, + fsrs: true, fsrs_reschedule: false, fsrs_health_check: true, }; From e1d8bca31ef6662c354cbb5d856e1109b92344c2 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 03:13:38 +0800 Subject: [PATCH 3/7] Add FSRS config key and disable FSRS in legacy scheduler tests - Add FSRS boolean config key to protobuf definition - Update generated Rust config mapping code - Disable FSRS in test_schedv3.py tests to maintain legacy scheduler behavior - These tests are designed for the old SM-2 algorithm, not FSRS --- proto/anki/config.proto | 1 + pylib/tests/test_schedv3.py | 3 +++ rslib/src/backend/config.rs | 1 + 3 files changed, 5 insertions(+) diff --git a/proto/anki/config.proto b/proto/anki/config.proto index ea115f0fc..1fe7011f8 100644 --- a/proto/anki/config.proto +++ b/proto/anki/config.proto @@ -57,6 +57,7 @@ message ConfigKey { LOAD_BALANCER_ENABLED = 26; FSRS_SHORT_TERM_WITH_STEPS_ENABLED = 27; FSRS_LEGACY_EVALUATE = 28; + FSRS = 29; } enum String { SET_DUE_BROWSER = 0; diff --git a/pylib/tests/test_schedv3.py b/pylib/tests/test_schedv3.py index a71fa7140..3021aca65 100644 --- a/pylib/tests/test_schedv3.py +++ b/pylib/tests/test_schedv3.py @@ -10,6 +10,7 @@ from typing import Dict import pytest from anki import hooks +from anki.config import Config from anki.consts import * from anki.lang import without_unicode_isolation from anki.scheduler import UnburyDeck @@ -19,6 +20,8 @@ from tests.shared import getEmptyCol as getEmptyColOrig def getEmptyCol(): col = getEmptyColOrig() + # Disable FSRS for legacy scheduler tests + col.set_config_bool(Config.Bool.FSRS, False, undoable=False) return col diff --git a/rslib/src/backend/config.rs b/rslib/src/backend/config.rs index b6e81ce2a..3d86dfc9b 100644 --- a/rslib/src/backend/config.rs +++ b/rslib/src/backend/config.rs @@ -40,6 +40,7 @@ impl From for BoolKey { BoolKeyProto::LoadBalancerEnabled => BoolKey::LoadBalancerEnabled, BoolKeyProto::FsrsShortTermWithStepsEnabled => BoolKey::FsrsShortTermWithStepsEnabled, BoolKeyProto::FsrsLegacyEvaluate => BoolKey::FsrsLegacyEvaluate, + BoolKeyProto::Fsrs => BoolKey::Fsrs, } } } From a137d980388471af77fb91793f5038263e8e7c46 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 03:19:13 +0800 Subject: [PATCH 4/7] Disable FSRS in state_application test This test validates legacy SM-2 scheduler behavior and expects specific card states without FSRS memory states. Disable FSRS to maintain test compatibility. --- rslib/src/scheduler/answering/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rslib/src/scheduler/answering/mod.rs b/rslib/src/scheduler/answering/mod.rs index 6ff8c6e2d..7b66ef5a4 100644 --- a/rslib/src/scheduler/answering/mod.rs +++ b/rslib/src/scheduler/answering/mod.rs @@ -706,6 +706,8 @@ pub(crate) mod test { #[test] fn state_application() -> Result<()> { let mut col = Collection::new(); + // Disable FSRS for this legacy scheduler test + col.set_config_bool(BoolKey::Fsrs, false, false)?; if col.timing_today()?.near_cutoff() { return Ok(()); } From 9d2ab84052ee2cc3869c5de7c4d473745437e481 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 03:22:28 +0800 Subject: [PATCH 5/7] Disable FSRS in scheduler queue tests Disable FSRS in review_queue_building and undo tests as they expect legacy SM-2 scheduler behavior for queue ordering and interval calculations. --- rslib/src/scheduler/queue/builder/mod.rs | 2 ++ rslib/src/scheduler/queue/undo.rs | 2 ++ 2 files changed, 4 insertions(+) diff --git a/rslib/src/scheduler/queue/builder/mod.rs b/rslib/src/scheduler/queue/builder/mod.rs index 064220bce..94ad02ba7 100644 --- a/rslib/src/scheduler/queue/builder/mod.rs +++ b/rslib/src/scheduler/queue/builder/mod.rs @@ -431,6 +431,8 @@ mod test { #[test] fn review_queue_building() -> Result<()> { let mut col = Collection::new(); + // Disable FSRS for this legacy scheduler test + col.set_config_bool(BoolKey::Fsrs, false, false)?; let mut deck = col.get_or_create_normal_deck("Default").unwrap(); let nt = col.get_notetype_by_name("Basic")?.unwrap(); diff --git a/rslib/src/scheduler/queue/undo.rs b/rslib/src/scheduler/queue/undo.rs index 02046eebc..21e8fba6d 100644 --- a/rslib/src/scheduler/queue/undo.rs +++ b/rslib/src/scheduler/queue/undo.rs @@ -100,6 +100,8 @@ mod test { fn undo() -> Result<()> { // add a note let mut col = Collection::new(); + // Disable FSRS for this legacy scheduler test + col.set_config_bool(BoolKey::Fsrs, false, false)?; let nid = add_note(&mut col, true)?; // turn burying and leech suspension on From 9c8f0ffc7d96d13f668d8ad83f094cb00d33d011 Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 03:31:04 +0800 Subject: [PATCH 6/7] Disable FSRS by default in test helper function Add Config import and disable FSRS in getEmptyCol() helper function. This ensures all tests using this helper function have FSRS disabled by default, maintaining compatibility with legacy scheduler tests. --- pylib/tests/shared.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pylib/tests/shared.py b/pylib/tests/shared.py index 6b653cf17..b0029962a 100644 --- a/pylib/tests/shared.py +++ b/pylib/tests/shared.py @@ -9,6 +9,7 @@ import tempfile import time from anki.collection import Collection as aopen +from anki.config import Config # Between 2-4AM, shift the time back so test assumptions hold. lt = time.localtime() @@ -49,6 +50,8 @@ def getEmptyCol(): (fd, path) = tempfile.mkstemp(suffix=".anki2") shutil.copy(_emptyCol, path) col = aopen(path) + # Disable FSRS for legacy scheduler tests + col.set_config_bool(Config.Bool.FSRS, False, undoable=False) return col From 1ac8769e30b85ad787c1fc1095317af0c66b68fd Mon Sep 17 00:00:00 2001 From: Jarrett Ye Date: Wed, 15 Oct 2025 09:17:33 +0800 Subject: [PATCH 7/7] Update schema11.rs --- rslib/src/config/schema11.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/rslib/src/config/schema11.rs b/rslib/src/config/schema11.rs index afbc398e6..9a284738f 100644 --- a/rslib/src/config/schema11.rs +++ b/rslib/src/config/schema11.rs @@ -25,6 +25,7 @@ pub(crate) fn schema11_config_as_string(creation_offset: Option) -> String "schedVer": 2, "creationOffset": creation_offset, "sched2021": true, + "fsrs": true, }); serde_json::to_string(&obj).unwrap() }