For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/llms-full.txt, and this page is available as Markdown at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/migration.md.
  • 繁體中文
  • 遷移至 v6 與 FSRS-7

    套件版本與模型版本是兩回事:ts-fsrs v5 已使用 FSRS-6。先將應用程式與儲存紀錄遷移至 v6 API,繼續使用 FSRS-6;再單獨遷移模型。本文對應本站的 v6 API,安裝時應鎖定與本文介面一致的 v6 版本。

    遷移後的程式碼不得使用 legacy API

    使用 defineScheduler 與明確的模型入口。遷移後不得使用 fsrs()、FSRS、createEmptyCard、generatorParameters、舊排程器類別與策略,或從根入口匯出的舊 Card、CardInput、ReviewLog、FSRSParameters 等 legacy 型別。部分符號仍為相容性而匯出,不代表它們是 v6 的整合方式。下文舊名稱僅供靜態對照;可執行範例不使用 legacy API 或型別。

    For your Agent
    讓 Agent 完成遷移

    複製給具有儲存庫存取權限的 Agent:先確認遷移目標,再整理變更 TODO List;使用者確認清單後才實作與驗證。

    1. 遷移至 v6 API,保留 FSRS-6

    定義排程策略

    defineScheduler({ model, chrono }) 建立可重用的定義;.use(...) 組合中介軟體並傳回新定義;.create({ config }) 驗證設定並建立獨立排程器實例。在程式層級保留定義,依使用者或牌組設定建立實例。

    單純的定義不包含全部 v5 排程策略。以下沿用目前標準預設的中介軟體順序:目標保留率、模糊、統計、已排程天數、學習步驟、最大間隔、單調間隔。請保留實際設定與 FSRS-6 權重。使用 dateChrono 時,fractionalDays: false 以 UTC 日曆日計算間隔;僅遷移 API 時,不應未經驗證就同時改變時間策略。

    import { 
    const dateChrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    dateChrono
    ,
    function defineScheduler<const M extends AnyModel, const C extends AnyChrono>(definition: {
        readonly model: M;
        readonly chrono: C;
    }): CustomScheduler<SchedulerNameOf<M>, SchedulerEnvFor<M, C, readonly []>, M, C>
    defineScheduler
    ,
    type Rating = 0 | 1 | 2 | 3 | 4
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    ,
    type State = 0 | 1 | 2 | 3
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    } from 'ts-fsrs'
    import {
    const schedulerDesiredRetentionMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>
    schedulerDesiredRetentionMiddleware
    ,
    const schedulerFuzzingMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>
    schedulerFuzzingMiddleware
    ,
    const schedulerLearningStepsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval?: number;
                readonly allowModelOverride?: boolean;
            };
            output: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval: number;
                readonly allowModelOverride: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
    }>
    schedulerLearningStepsMiddleware
    ,
    const schedulerMaximumIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after learning steps so explicit steps can keep their exact delay.

    schedulerMaximumIntervalMiddleware
    ,
    const schedulerMonotonicIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after fuzzing and learning steps, when present.

    schedulerMonotonicIntervalMiddleware
    ,
    const schedulerScheduledDaysMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
    }>

    Register before interval middleware so it records their final value on unwind.

    schedulerScheduledDaysMiddleware
    ,
    const schedulerStatsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly clearStatsOnForget?: boolean | undefined;
            };
            output: {
                readonly clearStatsOnForget: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly reps: number;
                readonly lapses: number;
            };
            output: {
                readonly reps: number;
                readonly lapses: number;
            };
        }>;
    }>
    schedulerStatsMiddleware
    ,
    } from 'ts-fsrs/middlewares' import {
    const FSRS6Model: Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>
    FSRS6Model
    ,
    const migrateFSRS6Parameters: (parameters?: readonly number[]) => number[]
    migrateFSRS6Parameters
    } from 'ts-fsrs/models/fsrs-6'
    // Keep the definition at application scope; create an instance per config. export const
    const definition: CustomScheduler<"fsrs-6", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    =
    defineScheduler<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>>(definition: {
        ...;
    }): CustomScheduler<...>
    defineScheduler
    ({
    model: Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>
    model
    :
    const FSRS6Model: Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>
    FSRS6Model
    ,
    chrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    chrono
    :
    const dateChrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    dateChrono
    ,
    }).
    CustomScheduler<"fsrs-6", SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, Model<...>, Chrono<...>>.use: <readonly [Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>, Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>, ... 4 more ..., Middleware<...>]>(middlewares_0: Middleware<...>, middlewares_1: Middleware<...>, middlewares_2: Middleware<...>, middlewares_3: Middleware<...>, middlewares_4: Middleware<...>, middlewares_5: Middleware<...>, middlewares_6: Middleware<...>) => CustomScheduler<...>

    Returns a new scheduler definition extended with the supplied middleware. The current scheduler and any cores created from it remain unchanged.

    use
    (
    const schedulerDesiredRetentionMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>
    schedulerDesiredRetentionMiddleware
    ,
    const schedulerFuzzingMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>
    schedulerFuzzingMiddleware
    ,
    const schedulerStatsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly clearStatsOnForget?: boolean | undefined;
            };
            output: {
                readonly clearStatsOnForget: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly reps: number;
                readonly lapses: number;
            };
            output: {
                readonly reps: number;
                readonly lapses: number;
            };
        }>;
    }>
    schedulerStatsMiddleware
    ,
    const schedulerScheduledDaysMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
    }>

    Register before interval middleware so it records their final value on unwind.

    schedulerScheduledDaysMiddleware
    ,
    const schedulerLearningStepsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval?: number;
                readonly allowModelOverride?: boolean;
            };
            output: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval: number;
                readonly allowModelOverride: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
    }>
    schedulerLearningStepsMiddleware
    ,
    const schedulerMaximumIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after learning steps so explicit steps can keep their exact delay.

    schedulerMaximumIntervalMiddleware
    ,
    const schedulerMonotonicIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after fuzzing and learning steps, when present.

    schedulerMonotonicIntervalMiddleware
    ) export const
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    =
    const definition: CustomScheduler<"fsrs-6", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    .
    CustomScheduler<"fsrs-6", ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>.create: (ctx: {
        readonly config: Omit<SchedulerConfigInput<Model<{
            readonly name: "fsrs-6";
            readonly config: SRSSchema<{
                input: {
                    readonly weights: number[];
                    readonly enableShortTerm: boolean;
                    readonly numRelearningSteps: number;
                };
                output: {
                    readonly weights: number[];
                    readonly enableShortTerm: boolean;
                    readonly numRelearningSteps: number;
                };
            }>;
            readonly memoryState: SRSSchema<{
                input: {
                    stability: number;
                    difficulty: number;
                };
                output: {
                    stability: number;
                    difficulty: number;
                };
            }>;
            readonly algorithm: FSRS6Algorithm;
        }>, Chrono<...>, readonly []>, "fractionalDays" | ... 8 more ... | "clearStatsOnForget"> & {
            ...;
        };
    }) => SchedulerCore<...>
    create
    ({
    config: Omit<SchedulerConfigInput<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, "fractionalDays" | ... 8 more ... | "clearStatsOnForget"> & {
        ...;
    }
    config
    : {
    weights:
    function migrateFSRS6Parameters(parameters?: readonly number[]): number[]
    migrateFSRS6Parameters
    (), // Pass the user's existing FSRS-6 weights here.
    fractionalDays: false, enableShortTerm: true, numRelearningSteps: 1, // Keep equal to relearningSteps.length. desiredRetention: 0.9, learningSteps: ['1m', '10m'], relearningSteps: ['10m'], enableFuzz: false, maximumInterval: 36500, clearStatsOnForget: false, // Match v5 forget's default counter behavior. }, }) export type
    type Card = {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    = ReturnType<typeof
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.newCard: (options?: (Omit<{
        readonly now?: Date | undefined;
    } & {
        readonly cardId?: string | number | undefined;
    }, "now"> & {
        readonly now?: Date | undefined;
    }) | undefined) => {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    newCard
    >
    export type
    type Revlog = {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    Revlog
    = ReturnType<typeof
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.review: (input: {
        readonly card: Readonly<Omit<Readonly<Omit<Readonly<{
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep?: number | undefined;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>;
        readonly grade: Grade;
        readonly now?: Date | undefined;
    }) => {
        ...;
    }
    review
    >['revlog']
    // An application's stored v5 record, not a legacy library type. type
    type StoredV5Card = {
        due: string;
        last_review?: string | null;
        stability: number;
        difficulty: number;
        state: State;
        scheduled_days: number;
        learning_steps: number;
        reps: number;
        lapses: number;
    }
    StoredV5Card
    = {
    due: string last_review?: string | null stability: number difficulty: number state:
    type State = 0 | 1 | 2 | 3
    State
    scheduled_days: number learning_steps: number reps: number lapses: number } export function
    function convertCard(stored: StoredV5Card, cardId: Card["cardId"]): Card
    convertCard
    (
    stored:
    type StoredV5Card = {
        due: string;
        last_review?: string | null;
        stability: number;
        difficulty: number;
        state: State;
        scheduled_days: number;
        learning_steps: number;
        reps: number;
        lapses: number;
    }
    StoredV5Card
    ,
    cardId:
    type Card = {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    ['cardId']
    ):
    type Card = {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    {
    const scheduleStatus = { [
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .New]: 'new',
    [
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .Learning]: 'learning',
    [
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .Review]: 'review',
    [
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .Relearning]: 'learning',
    } as const return
    const definition: CustomScheduler<"fsrs-6", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    .
    CustomScheduler<"fsrs-6", ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>.schema: SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>
    schema
    .
    SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>.card: SRSSchema<{
        input: Readonly<Omit<Readonly<{
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep?: number | undefined;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>;
        output: Mutable<...>;
    }>
    card
    .
    SRSSchema<{ input: Readonly<Omit<Readonly<{ stability: number; difficulty: number; } & { dueAt: Date; lastReviewAt: Date | null; } & SchedulerCoreFields$1<"new" | "learning" | "review">> & { ...; }, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>; output: Mutable<...>; }>.parse(input: unknown): Mutable<Omit<Mutable<{
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
    } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
        readonly cardId: string | number;
        readonly reps: number;
        readonly learningStep: number;
        readonly scheduledDays: number;
        readonly lapses: number;
    }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>
    parse
    ({
    cardId, dueAt: new Date(stored.due), lastReviewAt: stored.state ===
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .New || stored.last_review == null
    ? null : new Date(stored.last_review), stability: stored.stability, difficulty: stored.difficulty, state: stored.state, scheduleStatus: scheduleStatus[stored.state], scheduledDays: stored.scheduled_days, learningStep: stored.learning_steps, reps: stored.reps, lapses: stored.lapses, }) } export const storedCard = { due: '2026-01-03T00:00:00.000Z', last_review: '2026-01-01T00:00:00.000Z', stability: 2, difficulty: 5, state:
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .Review,
    scheduled_days: 2, learning_steps: 0, reps: 3, lapses: 0, } satisfies
    type StoredV5Card = {
        due: string;
        last_review?: string | null;
        stability: number;
        difficulty: number;
        state: State;
        scheduled_days: number;
        learning_steps: number;
        reps: number;
        lapses: number;
    }
    StoredV5Card
    const
    const card: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    card
    =
    function convertCard(stored: StoredV5Card, cardId: Card["cardId"]): Card
    convertCard
    (storedCard, 'card-1')
    // An overdue review: previous review, original due date and now are distinct. const now = new Date('2026-01-04T00:00:00.000Z') const
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    =
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.review: (input: {
        readonly card: Readonly<Omit<Readonly<Omit<Readonly<{
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep?: number | undefined;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>;
        readonly grade: Grade;
        readonly now?: Date | undefined;
    }) => {
        ...;
    }
    review
    ({ card, grade:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, now })
    const
    const restored: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    restored
    =
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-6";
        readonly config: SRSSchema<{
            input: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
            output: {
                readonly weights: number[];
                readonly enableShortTerm: boolean;
                readonly numRelearningSteps: number;
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stability: number;
                difficulty: number;
            };
            output: {
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS6Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-6"; readonly config: SRSSchema<{ input: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; output: { readonly weights: number[]; readonly enableShortTerm: boolean; readonly numRelearningSteps: number; }; }>; readonly memoryState: SRSSchema<{ input: { stability: number; difficulty: number; }; output: { stability: number; difficulty: number; }; }>; readonly algorithm: FSRS6Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.rollback: (input: {
        readonly card: Mutable<Omit<Mutable<Omit<Mutable<{
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep: number;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>;
        readonly revlog: Mutable<...>;
    }) => {
        ...;
    }
    rollback
    ({
    card: Mutable<Omit<Mutable<Omit<Mutable<{
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
    } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
        readonly cardId: string | number;
        readonly reps: number;
        readonly learningStep: number;
        readonly scheduledDays: number;
        readonly lapses: number;
    }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>
    card
    :
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    card
    ,
    revlog: Mutable<Omit<Mutable<Omit<Mutable<{
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
        reviewTime: Date;
    } & SchedulerCoreFields$1<"new" | "learning" | "review"> & {
        readonly rating: Grade;
    }> & {
        readonly cardId: string | number;
        readonly learningStep: number;
        readonly scheduledDays: number;
    }, "rating" | keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review"> & {
        readonly rating: Grade;
    }>, "rating" | keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...> & {
        readonly rating: Grade;
    }>
    revlog
    :
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    revlog
    ,
    }) console.log( JSON.stringify( { cardId:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    card
    .cardId,
    rating:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    revlog
    .rating,
    reps:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    card: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    card
    .reps,
    revlog: { lastReviewAt:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    revlog
    .lastReviewAt,
    dueAt:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    revlog
    .dueAt,
    reviewTime:
    const result: {
        card: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            reps: number;
            learningStep: number;
            scheduledDays: number;
            lapses: number;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
        };
        revlog: {
            cardId: string | number;
            stability: number;
            difficulty: number;
            dueAt: Date;
            lastReviewAt: Date | null;
            learningStep: number;
            scheduledDays: number;
            reviewTime: Date;
            state: State;
            scheduleStatus: "new" | "learning" | "review";
            rating: Grade;
        };
    }
    result
    .
    revlog: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        learningStep: number;
        scheduledDays: number;
        reviewTime: Date;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        rating: Grade;
    }
    revlog
    .reviewTime,
    }, rollbackDueAt:
    const restored: {
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    restored
    .dueAt,
    }, null, 2 ) )

    區域型別 StoredV5Card 描述應用程式的儲存格式,並非從 legacy 函式庫匯入。以資料庫既有的穩定 ID 作為 cardId,另外保留應用程式自有欄位。組合後的卡片 schema 會驗證轉換後的日期與欄位;其他應用程式欄位也應在讀取儲存資料的邊界驗證。

    設定對照

    v5 設定v6 設定遷移說明
    wweights此階段保留使用者的 FSRS-6 權重;範例僅為方便執行才使用預設值。
    request_retentiondesiredRetention需要目標保留率中介軟體。
    maximum_intervalmaximumInterval需要最大間隔中介軟體;單調間隔策略也使用此上限。
    enable_fuzzenableFuzz需要模糊中介軟體,保留舊設定。
    enable_short_termenableShortTerm對 FSRS-6,同時影響模型短期行為與明確的學習步驟。
    learning_steps / relearning_stepslearningSteps / relearningSteps保留設定的步驟陣列與既有學習進度。
    重新學習步驟數量numRelearningStepsFSRS-6 需設為 relearningSteps.length。
    forget(..., reset_count)clearStatsOnForget改為實例設定;v5 預設 false,v6 統計中介軟體預設 true。

    卡片、紀錄與操作

    v5 儲存欄位v6 欄位或處理方式
    due卡片的 dueAt,反序列化為 Date。
    elapsed_days / 紀錄 last_elapsed_days已移除,使用所選 chrono 由時間戳記計算經過天數;FSRS-7 重播不要使用這些舊的取整值。
    last_reviewlastReviewAt,缺少或 null 統一為 null。
    scheduled_daysscheduledDays,由中介軟體提供。
    learning_stepslearningStep,由中介軟體提供。
    stability、difficulty、state、reps、lapsesAPI 遷移時保留;統計欄位需要中介軟體。
    應用程式紀錄 IDcardId,卡片與紀錄使用同一 ID。
    無對應欄位scheduleStatus:New → new,Learning/Relearning → learning,Review → review。
    複習紀錄 reviewreviewTime,即實際複習時間,而非卡片到期時間。
    結果 { card, log }{ card, revlog }。

    如範例所示,從排程器推導型別。卡片與紀錄欄位取決於模型、chrono 及中介軟體。自訂 v5 策略需改寫為對應的中介軟體 hook,不能只改名或繼續繼承舊排程器。

    v5 操作(僅供對照)v6 操作
    createEmptyCard(now)scheduler.newCard({ now, cardId })
    f.next(card, now, grade)scheduler.review({ card, now, grade })
    f.repeat(card, now)scheduler.preview({ card, now }) 傳回可迭代物件,透過 Symbol.iterator 提供 iterator,可用 for...of 遍歷。每個候選項包含 { grade, card, revlog },透過 candidate.grade 選取,不再以評分鍵索引物件。
    f.rollback(card, log)scheduler.rollback({ card, revlog }),使用傳回的 v6 紀錄。
    f.forget(card, now, reset_count)scheduler.forget({ card, now });傳回卡片,而非 { card, log },手動操作紀錄由應用程式保存。
    f.get_retrievability(card, now, false)對有 lastReviewAt 的已學習卡片,呼叫 scheduler.model.forgettingCurve(card, scheduler.chrono.difference(card.lastReviewAt, now)),傳回數值;新卡片另外處理,百分比由應用程式格式化。

    review() 傳回新資料,應同時保存 result.card 與 result.revlog。新紀錄保存復原所需的複習前欄位,包含 dueAt、lastReviewAt。不能只將舊紀錄的 due 改名就用於 v6 復原:舊紀錄可能缺少必要的複習前快照。保留原始歷史,僅轉換評分與實際複習時間用於模型重播。跨版本復原需要獨立的應用程式快照或復原邊界。

    即使模型與設定相同,也不保證所有學習步驟或模糊情境的間隔與 v5 完全一致。切換寫入前,應檢查 New、Learning、Review、Relearning 的代表卡片。DefaultScheduler 是另一個預設入口,但預設模型為 FSRS-7;若在此階段採用它,應明確指定 FSRS-6。

    為什麼紀錄中的三個時間不能直接改名

    dateChrono 的欄位名稱是 reviewTime,不是 reviewAt。以逾期複習為例:卡片上次於 1 月 1 日複習,原訂 1 月 3 日到期,實際於 1 月 4 日複習。

    含義v5 一般複習紀錄v6 revlog
    上次複習時間:1 月 1 日due(舊實作寫入 card.last_review || card.due)lastReviewAt
    原訂到期時間:1 月 3 日此已學習卡片沒有另外記錄dueAt
    本次實際複習時間:1 月 4 日reviewreviewTime

    lastReviewAt 表示本次複習之前的上次複習時間,輸入與輸出的型別有所不同:

    • 輸入 DateRevlogInputFields 中是可選的 lastReviewAt?: Date | null。省略或傳入 undefined 時,schema 會將其正規化為 null;dueAt 與 reviewTime 仍必須是有效的 Date。
    • 輸出 DateRevlogFields 中始終存在 lastReviewAt: Date | null。正常的已學習卡片紀錄保存複習前的 card.lastReviewAt;沒有上次複習的新卡片,首次複習紀錄中的值為 null。
    • null 不會自動推算缺少的上次複習時間。舊紀錄缺少此資訊時,通過 schema 驗證不代表能精確復原;不要以 dueAt 或 reviewTime 代替它。

    複習傳回的卡片中,lastReviewAt 已變成 1 月 4 日,dueAt 是新計算的到期時間;紀錄保存的是複習前的時間。使用這張卡片與 v6 紀錄復原後,dueAt 恢復為 1 月 3 日,lastReviewAt 恢復為 1 月 1 日,提前或逾期複習皆然。這正是 chrono 重構時分開「計算經過天數的時間」與「供復原使用的原到期時間」的原因。上面的可執行範例會印出這三個欄位。

    不能一律執行 oldLog.due → revlog.dueAt:一般 v5 已學習卡片紀錄的 due 通常是上次複習時間;沒有 last_review 的首次複習才記錄原到期時間,Manual/遺忘紀錄又有各自的語意。v5 重設後的 New 卡片也可能帶有舊 last_review,因此卡片轉換範例對 State.New 統一輸出 lastReviewAt: null。

    只重建模型記憶時,僅映射 rating 與 review → reviewTime 即可。若要跨版本精確復原,需要原始複習前卡片快照(包含兩個時間欄位與中介軟體欄位),否則應設立復原邊界。不能以 review 或重新計算的間隔補造過去未記錄的到期時間,尤其是在提前複習、學習步驟、模糊或手動調整之後。

    2. 從 FSRS-6 遷移至 FSRS-7

    權重與狀態屬於各自的模型

    FSRS-6 使用 21 個權重,FSRS-7 需要獨立的 34 個權重。使用 FSRS7_DEFAULT_WEIGHTS,或重新訓練 FSRS-7 權重。不要替 FSRS-6 參數補值,也不要重用其訓練權重。migrateFSRS7Parameters 僅為空輸入提供預設值,不會轉換舊模型的參數配置。

    FSRS-7 記憶狀態包含 stability、stabilityFast 與 difficulty,三個欄位都應透過歷史重建。重建結果僅用於更新目前 card 的記憶狀態(memoryState);歷史 revlog 僅作為唯讀輸入,不得修改、覆寫或補寫其中的任何資料,包括過去記錄的記憶狀態。

    不得為既有卡片直接設定 stabilityFast = 0.8 * stability,也不能保留 FSRS-6 的穩定性、難度後只新增快分量。模型初始化使用的係數不是已演化記憶狀態的遷移公式。

    設定 fractionalDays: true,保留兩次複習相隔十分鐘等小數天數。FSRS-7 的快軌跡是模型固有部分:安裝學習步驟中介軟體後,enableShortTerm: false 僅關閉明確的學習步驟,不會關閉快軌跡。FSRS-7 模型沒有與 FSRS-6 的 numRelearningSteps 對應的設定項目。

    FSRS-7 的預設步驟與學習狀態

    DefaultScheduler 對 FSRS-7 與 FSRS-3~6 一樣預設使用學習步驟 ['1m', '10m'] 與重新學習步驟 ['10m'],並開啟 allowModelOverride,讓較長的模型間隔覆寫目前步驟。明確傳入的步驟不會被預設值覆寫。enableShortTerm 仍預設 true,控制明確的步驟,不控制 FSRS-7 快軌跡或依間隔劃分的學習狀態。

    註冊 schedulerLearningStepsMiddleware 後,狀態由最終排程間隔決定,即使步驟關閉、為空或已完成:

    複習前狀態最終間隔小於 graduatingInterval(預設一天)最終間隔至少 graduatingInterval
    New / LearningLearning,scheduleStatus: learningReview,scheduleStatus: review
    Review / RelearningRelearning,scheduleStatus: learningReview,scheduleStatus: review

    設定了步驟時,沒有適用步驟的 Hard、Good、Easy 至少在 graduatingInterval 之後到期,因此走完步驟,以及 Review 卡片按 Hard、Good 或 Easy,都會進入 Review。開啟 allowModelOverride 時,使用模型間隔的 Again 總是進入 Learning/Relearning,即使其間隔被限制為 graduatingInterval。

    沒有設定步驟時,不能假設「沒有 Learning」、「只有 Again 才進入 Relearning」或「Easy 一定進入 Review」。一般來說,Easy 跳過明確的步驟,Good 僅在存在適用的下一步驟時推進,時長為 0 的步驟視為沒有步驟。learningStep 只在卡片留在 Learning/Relearning 時保留下一步驟,卡片進入 Review 時重設為 0;它是步驟索引,不是複習次數。

    這些轉換屬於中介軟體,不屬於 FSRS7Model。只組合模型與 chrono 的排程器仍傳回 Review,即使間隔小於一天。遷移應用程式佇列、狀態篩選與統計時,需要同步調整依賴舊行為的判斷。

    「重播記憶,保留排程安排」一節的完整遷移範例明確保留既有學習步驟,不依賴預設值。若產品決定完全採用模型驅動的步驟,可明確設定 learningSteps: []、relearningSteps: [];這不等於移除學習步驟中介軟體。改變步驟策略應單獨驗證,不能在卡片欄位遷移時順便執行。

    遷移回憶機率呼叫

    使用 scheduler.model.forgettingCurve(state, elapsedDays) 取得數值回憶機率,或 scheduler.model.algorithm.curve(elapsedDays, state) 檢查快慢分量。兩者皆需要完整 FSRS-7 狀態:stability、stabilityFast、difficulty,不能只傳 FSRS-6 的單一穩定性值。

    也可以從 ts-fsrs/models/fsrs-7 匯入獨立函式 curve,呼叫 curve(weights, elapsedDays, state),不必建立演算法實例;weights 必須是有效的 34 個 FSRS-7 權重。此函式不驗證權重:儲存或使用者輸入應先通過 schema/參數驗證,不要用它探測權重是否有效。使用已遷移的記憶狀態與同一份 FSRS-7 權重,elapsedDays 保留小數天數。

    曲線結果包含 retrievability、derivative、fast、slow、fastWeight、slowWeight 與 total;total = fastWeight + slowWeight 是混合係數之和,不是總回憶機率。替代舊回憶機率呼叫時讀取 retrievability,百分比由應用程式格式化。演算法實例的曲線結果也包含 total。這些曲線介面只計算機率與分量,不遷移卡片、產生紀錄或安排到期時間。

    重播記憶,保留排程安排

    以下為可獨立執行的範例。它接收已轉為 v6 結構的 FSRS-6 卡片,將儲存紀錄的 review 轉成 reviewTime,呼叫 Reschedule.replay(),不傳入舊模型的 initialState。遷移時只重建記憶狀態,不重新安排既有卡片的下次複習時間(dueAt)。之後使用者複習該卡片時,再由 FSRS-7 計算新的下次複習時間。ID、上次複習時間、學習進度與統計也保持不變。

    import { 
    const dateChrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    dateChrono
    ,
    function defineScheduler<const M extends AnyModel, const C extends AnyChrono>(definition: {
        readonly model: M;
        readonly chrono: C;
    }): CustomScheduler<SchedulerNameOf<M>, SchedulerEnvFor<M, C, readonly []>, M, C>
    defineScheduler
    ,
    type Rating = 0 | 1 | 2 | 3 | 4
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    ,
    type State = 0 | 1 | 2 | 3
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    } from 'ts-fsrs'
    import {
    const schedulerDesiredRetentionMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>
    schedulerDesiredRetentionMiddleware
    ,
    const schedulerFuzzingMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>
    schedulerFuzzingMiddleware
    ,
    const schedulerLearningStepsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval?: number;
                readonly allowModelOverride?: boolean;
            };
            output: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval: number;
                readonly allowModelOverride: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
    }>
    schedulerLearningStepsMiddleware
    ,
    const schedulerMaximumIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after learning steps so explicit steps can keep their exact delay.

    schedulerMaximumIntervalMiddleware
    ,
    const schedulerMonotonicIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after fuzzing and learning steps, when present.

    schedulerMonotonicIntervalMiddleware
    ,
    const schedulerScheduledDaysMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
    }>

    Register before interval middleware so it records their final value on unwind.

    schedulerScheduledDaysMiddleware
    ,
    const schedulerStatsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly clearStatsOnForget?: boolean | undefined;
            };
            output: {
                readonly clearStatsOnForget: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly reps: number;
                readonly lapses: number;
            };
            output: {
                readonly reps: number;
                readonly lapses: number;
            };
        }>;
    }>
    schedulerStatsMiddleware
    ,
    } from 'ts-fsrs/middlewares' import {
    const FSRS7_DEFAULT_WEIGHTS: number[]
    FSRS7_DEFAULT_WEIGHTS
    ,
    const FSRS7Model: Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>
    FSRS7Model
    } from 'ts-fsrs/models/fsrs-7'
    import {
    class Reschedule<Scheduler extends AnySchedulerCore>

    Replays a review history on top of an existing srs-kit scheduler core.

    The scheduler instance keeps the model and chronology coupled, allowing the review-time, card and memory-state types to be inferred from the selected core.

    Reschedule
    } from 'ts-fsrs/reschedule'
    export const
    const definition: CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    =
    defineScheduler<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>>(definition: {
        ...;
    }): CustomScheduler<...>
    defineScheduler
    ({
    model: Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>
    model
    :
    const FSRS7Model: Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>
    FSRS7Model
    ,
    chrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    chrono
    :
    const dateChrono: Chrono<{
        readonly time: SRSSchema<{
            input: Date;
            output: Date;
        }>;
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly fields: {
            readonly card: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                };
            }>;
            readonly revlog: SRSSchema<{
                input: {
                    dueAt: Date;
                    lastReviewAt?: (Date | null) | undefined;
                    reviewTime: Date;
                };
                output: {
                    dueAt: Date;
                    lastReviewAt: Date | null;
                    reviewTime: Date;
                };
            }>;
        };
    }>
    dateChrono
    ,
    }).
    CustomScheduler<"fsrs-7", SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, Model<...>, Chrono<...>>.use: <readonly [Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>, Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>, ... 4 more ..., Middleware<...>]>(middlewares_0: Middleware<...>, middlewares_1: Middleware<...>, middlewares_2: Middleware<...>, middlewares_3: Middleware<...>, middlewares_4: Middleware<...>, middlewares_5: Middleware<...>, middlewares_6: Middleware<...>) => CustomScheduler<...>

    Returns a new scheduler definition extended with the supplied middleware. The current scheduler and any cores created from it remain unchanged.

    use
    (
    const schedulerDesiredRetentionMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly desiredRetention: number | Record<Grade, number>;
            };
            output: {
                readonly desiredRetention: Record<Grade, number>;
            };
        }>;
    }>
    schedulerDesiredRetentionMiddleware
    ,
    const schedulerFuzzingMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays?: boolean;
            };
            output: {
                readonly enableFuzz: boolean;
                readonly maximumInterval: number;
                readonly fractionalDays: boolean;
            };
        }>;
        readonly cardInitInput: SRSSchema<{
            input: {
                readonly cardId?: string | number;
            };
            output: {
                readonly cardId?: string | number;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly cardId: string | number;
                readonly reps: number;
            };
            output: {
                readonly cardId: string | number;
                readonly reps: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly cardId: string | number;
            };
            output: {
                readonly cardId: string | number;
            };
        }>;
    }>
    schedulerFuzzingMiddleware
    ,
    const schedulerStatsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly clearStatsOnForget?: boolean | undefined;
            };
            output: {
                readonly clearStatsOnForget: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly reps: number;
                readonly lapses: number;
            };
            output: {
                readonly reps: number;
                readonly lapses: number;
            };
        }>;
    }>
    schedulerStatsMiddleware
    ,
    const schedulerScheduledDaysMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly fractionalDays?: boolean | undefined;
            };
            output: {
                readonly fractionalDays: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly scheduledDays: number;
            };
            output: {
                readonly scheduledDays: number;
            };
        }>;
    }>

    Register before interval middleware so it records their final value on unwind.

    schedulerScheduledDaysMiddleware
    ,
    const schedulerLearningStepsMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval?: number;
                readonly allowModelOverride?: boolean;
            };
            output: {
                readonly learningSteps: readonly StepUnit[];
                readonly relearningSteps: readonly StepUnit[];
                readonly enableShortTerm: boolean;
                readonly graduatingInterval: number;
                readonly allowModelOverride: boolean;
            };
        }>;
        readonly card: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
        readonly revlog: SRSSchema<{
            input: {
                readonly learningStep?: number;
            };
            output: {
                readonly learningStep: number;
            };
        }>;
    }>
    schedulerLearningStepsMiddleware
    ,
    const schedulerMaximumIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after learning steps so explicit steps can keep their exact delay.

    schedulerMaximumIntervalMiddleware
    ,
    const schedulerMonotonicIntervalMiddleware: Middleware<symbol, {
        readonly config: SRSSchema<{
            input: {
                readonly maximumInterval?: number;
            };
            output: {
                readonly maximumInterval: number;
            };
        }>;
    }>

    Register after fuzzing and learning steps, when present.

    schedulerMonotonicIntervalMiddleware
    ) export const
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    =
    const definition: CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    .
    CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>.create: (ctx: {
        readonly config: Omit<SchedulerConfigInput<Model<{
            readonly name: "fsrs-7";
            readonly config: SRSSchema<{
                input: {
                    readonly weights: readonly number[];
                };
                output: {
                    readonly weights: readonly number[];
                };
            }>;
            readonly memoryState: SRSSchema<{
                input: {
                    stabilityFast: number;
                    stability: number;
                    difficulty: number;
                };
                output: {
                    stabilityFast: number;
                    stability: number;
                    difficulty: number;
                };
            }>;
            readonly algorithm: FSRS7Algorithm;
        }>, Chrono<...>, readonly []>, "fractionalDays" | ... 8 more ... | "clearStatsOnForget"> & {
            ...;
        };
    }) => SchedulerCore<...>
    create
    ({
    config: Omit<SchedulerConfigInput<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, "fractionalDays" | ... 8 more ... | "clearStatsOnForget"> & {
        ...;
    }
    config
    : {
    weights:
    const FSRS7_DEFAULT_WEIGHTS: number[]
    FSRS7_DEFAULT_WEIGHTS
    ,
    fractionalDays: true, enableShortTerm: true, // Controls learning steps, not the model's fast trace. desiredRetention: 0.9, // Preserve existing steps explicitly instead of inheriting preset defaults. learningSteps: ['1m', '10m'], relearningSteps: ['10m'], enableFuzz: false, maximumInterval: 36500, clearStatsOnForget: false, }, }) type
    type Card = {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    = ReturnType<typeof
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.newCard: (options?: (Omit<{
        readonly now?: Date | undefined;
    } & {
        readonly cardId?: string | number | undefined;
    }, "now"> & {
        readonly now?: Date | undefined;
    }) | undefined) => {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    newCard
    >
    type
    type PreviousCard = {
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
    }
    PreviousCard
    = Omit<
    type Card = {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    , 'stabilityFast'>
    type
    type StoredReview = {
        rating: Rating;
        review: string;
    }
    StoredReview
    = { rating:
    type Rating = 0 | 1 | 2 | 3 | 4
    Rating
    ; review: string }
    // completeHistory means all reviews since creation or the latest memory reset. // Decide this from application records, not from the number of rows alone. export function
    function migrateMemory(card: PreviousCard, logs: readonly StoredReview[], completeHistory: boolean): Card
    migrateMemory
    (
    card:
    type PreviousCard = {
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
    }
    PreviousCard
    ,
    logs: readonly
    type StoredReview = {
        rating: Rating;
        review: string;
    }
    StoredReview
    [],
    completeHistory: boolean ):
    type Card = {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    Card
    {
    if (card.state ===
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .New) {
    const { stability, stabilityFast, difficulty } =
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    .
    SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>.newCard: (options?: (Omit<{
        readonly now?: Date | undefined;
    } & {
        readonly cardId?: string | number | undefined;
    }, "now"> & {
        readonly now?: Date | undefined;
    }) | undefined) => {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    newCard
    ({
    cardId: card.cardId, }) return
    const definition: CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    .
    CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>.schema: SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>
    schema
    .
    SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>.card: SRSSchema<{
        input: Readonly<Omit<Readonly<{
            stabilityFast: number;
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep?: number | undefined;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>;
        output: Mutable<...>;
    }>
    card
    .
    SRSSchema<{ input: Readonly<Omit<Readonly<{ stabilityFast: number; stability: number; difficulty: number; } & { dueAt: Date; lastReviewAt: Date | null; } & SchedulerCoreFields$1<"new" | "learning" | "review">> & { ...; }, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>; output: Mutable<...>; }>.parse(input: unknown): Mutable<Omit<Mutable<{
        stabilityFast: number;
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
    } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
        readonly cardId: string | number;
        readonly reps: number;
        readonly learningStep: number;
        readonly scheduledDays: number;
        readonly lapses: number;
    }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>
    parse
    ({
    ...card, stability, stabilityFast, difficulty, }) } if (!completeHistory) throw new Error('Keep this card on FSRS-6: incomplete history') const history = logs .filter(({ rating }) => rating !==
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Manual)
    .map(({ rating, review }) => ({ rating, reviewTime: new Date(review), })) // replay validates dates/ratings and sorts the non-manual history. // Empty or Manual-only histories throw instead of clearing memory. const { memoryState } = new
    new Reschedule<SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>>(scheduler: SchedulerCore<...>): Reschedule<...>

    Replays a review history on top of an existing srs-kit scheduler core.

    The scheduler instance keeps the model and chronology coupled, allowing the review-time, card and memory-state types to be inferred from the selected core.

    Reschedule
    (
    const scheduler: SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>
    scheduler
    ).
    Reschedule<SchedulerCore<SchedulerCoreEnv<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>, ModelCore<...>, ChronoCore<...>>>.replay(input: ReplayInput<{
        stabilityFast: number;
        stability: number;
        difficulty: number;
    }, Date>, options?: RescheduleOptions): ReplayResult<{
        stabilityFast: number;
        stability: number;
        difficulty: number;
    }>

    Rebuilds model memory from the review history and returns the memory state after each review.

    replay
    ({
    ReplayInput<{ stabilityFast: number; stability: number; difficulty: number; }, Date>.history: readonly RescheduleReview<Date>[]
    history
    })
    const latestReview = history.reduce( (latest, { reviewTime }) => Math.max(latest, reviewTime.getTime()), -Infinity ) if (card.lastReviewAt?.getTime() !== latestReview) { throw new Error( 'Keep this card on FSRS-6: history does not match lastReviewAt' ) } // Only the model memory changes; dueAt, counters and learning progress survive. return
    const definition: CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>
    definition
    .
    CustomScheduler<"fsrs-7", ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>, Model<...>, Chrono<...>>.schema: SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{
        readonly name: "fsrs-7";
        readonly config: SRSSchema<{
            input: {
                readonly weights: readonly number[];
            };
            output: {
                readonly weights: readonly number[];
            };
        }>;
        readonly memoryState: SRSSchema<{
            input: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
            output: {
                stabilityFast: number;
                stability: number;
                difficulty: number;
            };
        }>;
        readonly algorithm: FSRS7Algorithm;
    }>, Chrono<...>, readonly []>, readonly [...]>>
    schema
    .
    SchedulerSchema<ExtendSchedulerEnv<SchedulerEnvFor<Model<{ readonly name: "fsrs-7"; readonly config: SRSSchema<{ input: { readonly weights: readonly number[]; }; output: { readonly weights: readonly number[]; }; }>; readonly memoryState: SRSSchema<{ input: { stabilityFast: number; stability: number; difficulty: number; }; output: { stabilityFast: number; stability: number; difficulty: number; }; }>; readonly algorithm: FSRS7Algorithm; }>, Chrono<...>, readonly []>, readonly [...]>>.card: SRSSchema<{
        input: Readonly<Omit<Readonly<{
            stabilityFast: number;
            stability: number;
            difficulty: number;
        } & {
            dueAt: Date;
            lastReviewAt: Date | null;
        } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
            readonly cardId: string | number;
            readonly reps: number;
            readonly learningStep?: number | undefined;
            readonly scheduledDays: number;
            readonly lapses: number;
        }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>;
        output: Mutable<...>;
    }>
    card
    .
    SRSSchema<{ input: Readonly<Omit<Readonly<{ stabilityFast: number; stability: number; difficulty: number; } & { dueAt: Date; lastReviewAt: Date | null; } & SchedulerCoreFields$1<"new" | "learning" | "review">> & { ...; }, keyof SchedulerCoreFields$1<...>> & SchedulerCoreFields$1<...>>; output: Mutable<...>; }>.parse(input: unknown): Mutable<Omit<Mutable<{
        stabilityFast: number;
        stability: number;
        difficulty: number;
    } & {
        dueAt: Date;
        lastReviewAt: Date | null;
    } & SchedulerCoreFields$1<"new" | "learning" | "review">> & {
        readonly cardId: string | number;
        readonly reps: number;
        readonly learningStep: number;
        readonly scheduledDays: number;
        readonly lapses: number;
    }, keyof SchedulerCoreFields$1<"new" | "learning" | "review">> & SchedulerCoreFields$1<"new" | "learning" | "review">>
    parse
    ({ ...card, ...memoryState })
    } export const previousCard:
    type PreviousCard = {
        state: State;
        scheduleStatus: "new" | "learning" | "review";
        cardId: string | number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
    }
    PreviousCard
    = {
    cardId: 'card-1', dueAt: new Date('2026-01-05T00:00:00.000Z'), lastReviewAt: new Date('2026-01-02T00:00:00.000Z'), stability: 2, difficulty: 5, state:
    const State: Readonly<{
        readonly New: 0;
        readonly Learning: 1;
        readonly Review: 2;
        readonly Relearning: 3;
    }>
    State
    .Review,
    scheduleStatus: 'review', scheduledDays: 3, learningStep: 0, reps: 3, lapses: 0, } export const storedHistory:
    type StoredReview = {
        rating: Rating;
        review: string;
    }
    StoredReview
    [] = [
    { rating:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, review: '2026-01-01T00:00:00.000Z' },
    { rating:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, review: '2026-01-01T00:10:00.000Z' },
    { rating:
    const Rating: Readonly<{
        readonly Manual: 0;
        readonly Again: 1;
        readonly Hard: 2;
        readonly Good: 3;
        readonly Easy: 4;
    }>
    Rating
    .Good, review: '2026-01-02T00:00:00.000Z' },
    ] const
    const migrated: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    migrated
    =
    function migrateMemory(card: PreviousCard, logs: readonly StoredReview[], completeHistory: boolean): Card
    migrateMemory
    (previousCard, storedHistory, true)
    console.log( JSON.stringify( { model: 'FSRS-7', cardId:
    const migrated: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    migrated
    .cardId,
    dueAt:
    const migrated: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    migrated
    .dueAt,
    reps:
    const migrated: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    migrated
    .reps,
    stabilityFast:
    const migrated: {
        cardId: string | number;
        stabilityFast: number;
        stability: number;
        difficulty: number;
        dueAt: Date;
        lastReviewAt: Date | null;
        reps: number;
        learningStep: number;
        scheduledDays: number;
        lapses: number;
        state: State;
        scheduleStatus: "new" | "learning" | "review";
    }
    migrated
    .stabilityFast,
    }, null, 2 ) )
    卡片或歷史情況處理方式
    新卡片(State.New),含主動重設後的卡片使用 FSRS-7 預設記憶狀態,保留排程與統計。
    已學習卡片,具有從建立或最近一次記憶重設以來的完整歷史使用 FSRS-7 權重重播,保存重建狀態並保留排程。
    歷史缺少或遭截斷卡片及其對應設定繼續使用 FSRS-6;不得默默清零,也不能僅憑列數宣稱歷史完整。
    已學習卡片的歷史為空或僅有 Manual重播拋錯,卡片繼續使用 FSRS-6。
    日期或評分無效,或最後一次複習與 lastReviewAt 不符停止該卡片遷移,先核對紀錄。

    replay() 依時間排序有效複習並過濾 Rating.Manual,但不會解讀手動遺忘或重設事件。應用程式必須選取最近一次記憶重設之後的完整歷史,排除更早的紀錄;僅手動調整到期時間不等於重設記憶。同一時間戳記的複習應保留紀錄順序。使用 dateChrono 時,時間需反序列化為有效的 Date。第一筆保留的複習從未初始化的記憶狀態開始,經過天數為零。

    範例中的歷史完整旗標由應用程式判斷,最後時間戳記相符並不能證明更早的複習沒有缺少。遷移失敗的卡片應依保存的模型版本繼續路由至 FSRS-6,不要將它們傳給 FSRS-7。

    如果確實需要重新安排到期時間

    new Reschedule(scheduler).reschedule({ history, initialCard }) 會透過整套排程策略重播,傳回 { card, results },可能改變到期時間、學習進度與統計。應以保留原 cardId、使用第一筆複習時間的 FSRS-7 新卡片作為 initialCard,不能在既有的已學習卡片上再重播完整歷史。產生的紀錄是重新計算的結果,不應替換原始歷史。本文預設使用 replay(),遷移時不重新安排既有卡片的下次複習時間。

    保存與驗收

    1. 備份卡片、原始紀錄與設定。為每張卡片或可靠關聯的設定保存模型版本,以及重播實際使用的權重。
    2. 增加 stabilityFast 與 v6 欄位的儲存,將重建記憶、模型版本及對應權重/設定參照一併提交,避免混用 FSRS-6 狀態與 FSRS-7 權重。保留應用程式 ID 與中繼資料。
    3. 保持原始紀錄不變,並建立復原邊界:舊模型紀錄不得直接用於 FSRS-7 rollback()。新的 FSRS-7 紀錄應保存 stabilityFast 與複習前欄位。
    4. 以代表卡片驗證複習、預覽、復原、同日複習、學習步驟及設定的模糊行為。僅遷移記憶時,斷言到期時間、ID、學習進度與統計不變。處理失敗後再切換對應卡片的模型。

    模型細節見 FSRS-7,API 組成見排程器定義、Chrono 與中介軟體。