Ebbinghaus Stability Updates — FSRS vs SM-2 Research #

Status: research complete, 2026-04-16 Covers: T50 (Implement Ebbinghaus stability updates) Conclusion: stick with simplified implicit-access formula; FSRS requires grade input reverie doesn’t have

Background #

The backlog (T50) proposes this stability update formula on each access:

S_new = S_old * (1 + a * exp(-S_old * interval))

This is an ad-hoc SM-2-inspired formula. FSRS v4 (2023, integrated into Anki Nov 2023) is the state-of-the-art SRS algorithm. This doc evaluates whether reverie should adopt FSRS formulas instead.


FSRS v4 — Full Mathematical Spec #

Types #

Retrievability (forgetting curve) #

R(t, S) = (1 + F · t/S)^C

where:
  F = 19/81 ≈ 0.2346
  C = -0.5
  t = days since last access

Reverie equivalent: this is what stability + time-decay factor represent in ADR-006.

Stability update — successful recall #

S'_r = S · (1 + t_d · t_s · t_r · h · b · e^W[8])

where:
  t_d = 11 − D                          (difficulty effect, linear)
  t_s = S^(−W[9])                       (large S → smaller increment)
  t_r = e^(W[10] · (1 − R)) − 1        (low R → larger increment)
  h   = W[15] if grade=Hard else 1.0    (Hard penalty)
  b   = W[16] if grade=Easy else 1.0    (Easy bonus)

Stability update — after forgetting (missed recall) #

S'_f = min(S_f, S)

where S_f = D^(−W[12]) · (S+1)^W[13] · e^(W[14]·(1−R)) · W[11]

Initial stability (first access, by grade) #

S_0(G) = W[G-1]

Defaults (W[0]-W[3]): [0.40255, 1.18385, 3.173, 15.69105]

→ Grade 1 (Again): S=0.40, Grade 4 (Easy): S=15.69

Difficulty update #

D_0(G) = W[4] − e^(W[5]·(G−1)) + 1   (initial, clamped [1,10])
D'    = D + ΔD · (10−D)/9             (linear damping toward neutral)
D''   = W[7]·D_0(4) + (1−W[7])·D'    (mean reversion)

ΔD = −W[6]·(G − 3)

Default weights (19 parameters) #

const W: [f64; 19] = [
    0.40255, 1.18385, 3.173,  15.69105,  // W[0-3]: initial stability by grade
    7.1949,  0.5345,  1.4604, 0.0046,    // W[4-7]: difficulty
    1.54575, 0.1192,  1.01925,1.9395,    // W[8-11]: recall stability
    0.11,    0.29605, 2.2698, 0.2315,    // W[12-15]: forget stability
    2.9898,  0.51655, 0.6621,            // W[16-18]: bonuses + decay
];

Why FSRS Does NOT Fit Reverie #

FSRS is designed for explicit grade input (Again/Hard/Good/Easy per review). Reverie has only implicit access signals: chunk was retrieved or not. No grade is collected.

RequirementFSRSReverie
Grade per accessRequiredNot available
Difficulty trackingPer-item D [1-10]Not tracked
User calibration19 learnable weightsNo training loop
Interval schedulingOutputs next-review dateNot scheduling reviews

FSRS would require inventing proxy grades (e.g., “how many results returned for this chunk?”) and a weight-tuning loop — complexity not justified at this stage.


The backlog formula is close but should use FSRS’s retrievability term for biological plausibility:

/// Update stability after implicit access.
/// Uses retrievability-based increment: higher recency bonus when chunk was "at risk".
pub fn update_stability(s_old: f32, age_days: f32) -> f32 {
    // Compute current retrievability at time of access
    let r = (1.0 + (19.0 / 81.0) * age_days / s_old).powf(-0.5);

    // Stability increment: larger when retrieved despite low retrievability (spaced effect)
    let learning_rate = 0.1_f32;
    let increment = learning_rate * (1.0 - r).max(0.0);

    (s_old * (1.0 + increment)).min(365.0) // cap at 1-year stability
}

This borrows the FSRS retrievability curve (R(t,S) power function) as the input to the increment, without requiring grades or difficulty tracking.

SHY interaction (T49 downscale) #

Dream downscale should multiply stability by the global scale factor only if chunk wasn’t accessed since the last cycle — mimicking SHY’s observation that consolidation occurs for memories NOT reactivated during NREM (they get re-normalized):

// In downscale phase: apply to non-accessed chunks only
if chunk.last_seen_at < cycle_start {
    chunk.stability = (chunk.stability * 0.95).max(MIN_STABILITY_FLOOR);
}
// Accessed chunks: stability was already updated at access time (above formula)

Prior Art / References #


Ticket Recommendation #

T50: Implement the revised formula above (retrievability-aware increment). Do NOT adopt full FSRS — grade input is unavailable. Tag: stability/ebbinghaus, not SM-2.

Surface to release as a research-finding: FSRS is worth revisiting if reverie ever adds explicit user feedback on chunk quality.