{
  "schema": "leumas.docs.page/1",
  "id": "adapter:domain/flashcards-srs",
  "slug": "adapters/domain/flashcards-srs",
  "kind": "capabilities",
  "bucket": "package",
  "title": "flashcards-srs",
  "name": "Flashcards Srs",
  "eyebrow": null,
  "chip": null,
  "summary": "Spaced-repetition scheduling engine for flashcards, study decks and memory apps: a pure, deterministic SM-2 (SuperMemo 2) implementation plus Leitner boxes and deck analytics. schedule takes one...",
  "keywords": [
    "flashcards-srs",
    "spaced-repetition",
    "flashcards",
    "study",
    "sm-2",
    "flashcards srs api",
    "leumas flashcards srs",
    "supermemo"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# flashcards-srs\n\nSpaced-repetition scheduling engine for flashcards, study decks and memory apps — a pure, deterministic\n**SM-2 (SuperMemo 2)** implementation plus the classic **Leitner** box system and deck analytics.\nPackaged as a Leumas \"intelligent microservice\" adapter pack.\n\nEvery tool has a deterministic algorithmic core that works fully **offline** with no model. A couple of\ntools (`schedule`, `difficulty`) can *optionally* enrich their study tip with an LLM when one is\nreachable (via `../_shared/llm.js`), and silently fall back to a templated tip otherwise. Results carry a\n`mode: 'heuristic' | 'llm'` tag when the LLM path is enabled.\n\n## Tools\n\n| Tool | Input | Returns |\n|---|---|---|\n| `schedule` | `{ card, grade, date?, options? }` | One SM-2 step: next `intervalDays`, updated `ease`, `repetitions`, `lapses`, `phase`, `due` date. Grade `<3` lapses the card (reset to 1 day). |\n| `review` | `{ cards, date?, options? }` | Batch SM-2 — advances an array of `{ ...cardState, grade }` cards; returns per-card next state + deck accuracy/avg interval. |\n| `leitner` | `{ card?, box?, correct, date?, options? }` | Moves a card up one Leitner box on correct recall, resets to box 1 on incorrect; returns new box, interval and due date. |\n| `dueToday` | `{ cards, date?, options? }` | Buckets a deck into `overdue`, `dueNow`, `upcoming` (within `horizonDays`) and new cards; returns the flat `due` id list. |\n| `deckStats` | `{ cards, date?, options? }` | Deck aggregate: state distribution (new/learning/review/mature), avg ease, maturity %, difficulty mix, and a day-by-day due forecast. |\n| `difficulty` | `{ card, options? }` | Classifies a card `easy`/`medium`/`hard`/`leech` with a 0-100 difficulty index and a remediation tip. |\n| `retentionEstimate` | `{ card, date?, options? }` | Forgetting-curve `R(t)=exp(-t/S)` recall probability now + the optimal next review for a `targetRetention`. |\n\n## Card shape\n\nAll tools accept a defensive card object (all keys optional, sensible defaults applied):\n\n```json\n{ \"id\": \"capital-of-france\", \"ease\": 2.5, \"interval\": 6, \"repetitions\": 2, \"lapses\": 0,\n  \"box\": 3, \"due\": \"2026-07-20\", \"lastReviewed\": \"2026-07-14\" }\n```\n\n## Usage\n\n```js\nimport srs from './index.js';\n\n// SM-2: a card recalled perfectly (grade 5) after 2 prior reps\nsrs.adapters.schedule({ card: { ease: 2.5, interval: 6, repetitions: 2 }, grade: 5 });\n// -> { mode:'heuristic', ease:2.6, intervalDays:16, repetitions:3, phase:'review', due:'2026-07-30', ... }\n\n// Leitner: a wrong answer drops the card to box 1\nsrs.adapters.leitner({ card: { id: 'x', box: 4 }, correct: false });\n// -> { fromBox:4, box:1, intervalDays:1, due:'2026-07-15', note:'Incorrect — reset to box 1...' }\n\n// What's due\nsrs.adapters.dueToday({ cards: deck, date: '2026-07-14' });\n```\n\n## SM-2 algorithm (implemented exactly)\n\n- `grade q ∈ 0..5`. `q < 3` ⇒ lapse: repetitions → 0, interval → 1 day, lapse counter +1.\n- `EF' = EF + (0.1 - (5-q)·(0.08 + (5-q)·0.02))`, floored at **1.3**.\n- Interval: rep 1 → 1 day, rep 2 → 6 days, rep n>2 → `round(prevInterval × EF')`.\n\n## DRY boundary\n\nNew capability — a memory/learning scheduler. It deliberately does **not** overlap:\n- `datetime` / `ical` — generic date math and calendar-file generation (this owns study scheduling logic).\n- `numbers` / `statistics` — generic numeric/series math (this owns the SM-2, Leitner and forgetting-curve models).\n- `cron` — interval-string parsing (`5m`); unrelated to review scheduling.\n\nSelf-contained: Node built-ins only, zero npm deps. The only cross-pack import is `../_shared/llm.js`\nfor the optional study-tip enrichment.\n",
  "source": {
    "path": "shared/engines/adapters/domain/flashcards-srs/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 3887,
    "hash": "e576379650974e2a50230cd77860e0748e4ffa34"
  },
  "urls": {
    "html": "/p/adapters/domain/flashcards-srs",
    "json": "/docs/adapters/domain/flashcards-srs.json",
    "md": "/docs/adapters/domain/flashcards-srs.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
