memory-engine is a TypeScript learning engine workspace for spaced
repetition, answer grading, modular API design, and dogfood client experiments.
It started as a framework-free kernel extracted from four learning apps:
- Ruminatio
- Scry
- Caesar in a Year
- Vault SRS
Scry and the Vault FSRS app are now decommission targets. The current product direction is a world-class modular API for building learning and memorization applications, plus experimental clients that dogfood the API. Winning clients can be extracted into their own repositories after executable evidence.
- Canonical learning-domain types
- FSRS state transitions
- Deterministic grading
- Progression and queue primitives
- Recitation grading
- Async rubric grading contracts
- Vendor-neutral rubric adapter interfaces
- Fixture corpora for contract and interface tests
- Evals and benchmarks for learning-behavior regressions
- Experimental clients that consume the API from outside
src/
The core runtime under src/ stays framework-free. Service, storage, UI, auth,
content parsing, and deployment experiments must live outside that pure kernel
until dogfood evidence proves a stable boundary.
Slices 1 through 3 are in place:
- canonical types
- FSRS scheduler wrapper
- deterministic grader
- progression metadata and eligibility helpers
- queue candidate filtering and selection
- deterministic recitation grading
- async rubric grading surface
- dedicated
memory-engine/adaptersrubric adapter subpath - exported test fixtures
- historical Scry and Vault SRS canary branches
Roadmap and shaping docs:
Active backlog now tracks Slice 5: modular API entrypoints, service-boundary failure semantics, evals/benchmarks, CLI dogfood, import probes, web-shell dogfood, and extraction gates.
Local path dependency:
{
"dependencies": {
"memory-engine": "file:../memory-engine"
}
}Workspace-style usage also works as long as the package is linked into the consuming repo.
import { Grader } from 'memory-engine/grading';
import { next } from 'memory-engine/scheduling';
import type { ReviewUnitId } from 'memory-engine/types';
const grader = new Grader();
const reviewUnitId = 'latin-1' as ReviewUnitId;
const grade = grader.grade(
{
kind: 'shortAnswer',
reviewUnitId,
prompt: 'Translate poena',
acceptedAnswers: ['punishment'],
equivalenceGroups: [],
ignoredTokens: [],
},
'Punishment',
{ responseTimeMs: 3200, priorReps: 3 },
);
const nextState = next(null, grade.rating, Date.now());Test fixtures for contract and interface tests:
import {
gradingFixtures,
progressionFixtures,
queueFixtures,
recitationFixtures,
schedulerFixtures,
} from 'memory-engine/testkit';Rubric adapters live on a separate subpath:
import { StaticRubricGrader } from 'memory-engine/adapters';bun install
git config core.hooksPath .githooks
bun run ci:local
bun run ci
dagger call check --source=.MIT