From 0119048c82a17d4b4639bd2e95002601578b13ee Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Mon, 31 Aug 2026 12:48:33 +0200 Subject: [PATCH] fix(srs): retain scheduled cards after course updates --- backend/services/vocabService.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index 03efa3f..19df4d4 100755 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -2060,22 +2060,19 @@ export default class VocabService { ['stage', 'ASC'] ] }); - const validPool = await this.getCompletedLessonVocabPool(hashedUserId, course.id); - const validPairs = new Set( - (Array.isArray(validPool?.vocabs) ? validPool.vocabs : []) - .map((entry) => this._buildSrsPairFingerprint(entry)) - .filter(Boolean) - ); + // Do not require a scheduled card to be present verbatim in today's + // regenerated lesson pool. Course content can be corrected after a card + // has been scheduled; comparing against the regenerated pool then hid all + // legitimate older SRS cards. `_isTrainableSrsPair` above remains the + // content-level guard for malformed fragments, hints and task prompts. const validDueRows = scheduledRows.filter((item) => this._isTrainableSrsPair(item) - && (!validPairs.size || validPairs.has(this._buildSrsPairFingerprint(item))) && this._getSrsScheduleDateKey(item.nextDueAt) <= todayKey ); const upcomingByDate = new Map(); scheduledRows .filter((item) => ( this._isTrainableSrsPair(item) - && (!validPairs.size || validPairs.has(this._buildSrsPairFingerprint(item))) && this._getSrsScheduleDateKey(item.nextDueAt) > todayKey )) .forEach((item) => {