6.7 KiB
6.7 KiB
Feature — Learning & Spaced Repetition
Structured learning paths with lessons, SM-2 spaced repetition, mastery tracking, verification queries, and preferred learning time windows.
Schema
learning_paths
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
uuid |
PK | |
domain_id |
uuid |
FK → domains.id, NOT NULL |
|
project_id |
uuid |
FK → projects.id, NOT NULL, ON DELETE CASCADE |
|
goal_id |
uuid |
FK → goals.id, nullable, ON DELETE SET NULL |
Linked goal |
title |
varchar(255) |
NOT NULL | |
description |
text |
nullable | |
status |
varchar(20) |
default 'active' |
active, paused, completed |
difficulty |
varchar(20) |
default 'beginner' |
|
estimated_hours |
real |
nullable | |
preferred_learning_times |
jsonb |
nullable | Array of time windows { startHour, endHour, dayOfWeek? } |
sort_order |
integer |
default 0 |
|
tags |
text[] |
default '{}' |
Indexes: domain_id, project_id, goal_id, status
lessons
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
uuid |
PK | |
learning_path_id |
uuid |
FK → learning_paths.id, ON DELETE CASCADE |
|
title |
varchar(255) |
NOT NULL | |
content |
text |
nullable | Lesson material |
key_concepts |
text[] |
default '{}' |
|
prerequisites |
uuid[] |
default '{}' |
Lesson IDs |
sort_order |
integer |
default 0 |
|
estimated_minutes |
integer |
nullable | |
sources |
text[] |
default '{}' |
Reference URLs/books |
assignments |
jsonb |
nullable | Structured assignments |
verification_query |
jsonb |
nullable | DB query to verify real-world practice |
Indexes: learning_path_id, sort_order
lesson_progress
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
uuid |
PK | |
lesson_id |
uuid |
UNIQUE, NOT NULL | One-to-one with lesson |
mastery_state |
varchar(20) |
default 'new' |
new, learning, reviewing, mastered |
ease_factor |
decimal(4,2) |
default 2.5 |
SM-2 ease factor |
interval_days |
integer |
default 0 |
Current review interval |
repetition_count |
integer |
default 0 |
|
next_review_at |
timestamptz |
nullable | |
last_reviewed_at |
timestamptz |
nullable | |
last_quality_rating |
integer |
nullable | 0-5 |
Indexes: next_review_at, mastery_state
review_logs
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
uuid |
PK | |
lesson_progress_id |
uuid |
FK → lesson_progress.id, ON DELETE CASCADE |
|
lesson_id |
uuid |
FK → lessons.id, ON DELETE CASCADE |
|
quality_rating |
integer |
NOT NULL | 0-5 (SM-2 scale) |
response_time_ms |
integer |
nullable | |
ease_factor |
decimal(4,2) |
NOT NULL | EF at time of review |
interval_days |
integer |
NOT NULL | Interval at time of review |
notes |
text |
nullable | Prefixed with [verification_failed] if verification failed |
Indexes: lesson_progress_id, lesson_id
API
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/learning/paths |
List paths (paginated, ?domainId=, ?status=, ?difficulty=, ?search=) |
GET |
/api/learning/paths/:id |
Get path with lessons and progress |
POST |
/api/learning/paths |
Create learning path |
PATCH |
/api/learning/paths/:id |
Update path |
DELETE |
/api/learning/paths/:id |
Delete path |
GET |
/api/learning/paths/:id/stats |
Path completion stats |
GET |
/api/learning/paths/:id/lessons |
List lessons in path (paginated, ?masteryState=) |
POST |
/api/learning/lessons |
Create lesson (auto-creates progress record) |
GET |
/api/learning/lessons/:id |
Get lesson with progress |
PATCH |
/api/learning/lessons/:id |
Update lesson |
DELETE |
/api/learning/lessons/:id |
Delete lesson |
POST |
/api/learning/lessons/:id/review |
Record review { qualityRating, responseTimeMs?, notes? } |
GET |
/api/learning/lessons/:id/reviews |
Review history |
GET |
/api/learning/due |
Lessons due for review (?limit=) |
GET |
/api/learning/stats |
Stats across all active paths |
Due Response
{
"reviewsDue": [{ "lesson": {...}, "progress": {...}, "path": { "id": "...", "title": "..." } }],
"nextNew": { "lesson": {...}, "path": {...} },
"totalDue": 5,
"inLearningWindow": true
}
Stats Response
{
"pathId": "...",
"title": "TypeScript Mastery",
"totalLessons": 20,
"mastered": 8,
"reviewing": 5,
"learning": 3,
"new": 4,
"completionPct": 40,
"nextReviewAt": "2026-03-09T14:00:00Z"
}
Backend Module
LearningModule — imports ProjectsModule.
SM-2 Algorithm:
- Quality rating 0-5 (0-2 = fail, 3-5 = pass)
- Pass: increment repetition, compute interval (1d → 6d → interval * EF)
- Fail: reset repetition to 0, interval back to 1d
- EF adjusted:
EF + (0.1 - (5-q) * (0.08 + (5-q) * 0.02)), min 1.3
Mastery states:
new— never reviewedlearning— 1 successful repetitionreviewing— 2+ repetitionsmastered— 5+ repetitions with EF >= 2.0
Verification queries:
- Lessons can define a
verificationQuerythat checks real-world data (e.g., "has 3 food entries this week") - If verification fails, quality rating is capped at 2, blocking mastery progression
- Supports conditions:
count_gte,has_entries,latest_value_gte,streak_gte - Timeframes:
day,week,month,all_time
Learning time windows:
- Paths define
preferredLearningTimeswithstartHour,endHour, optionaldayOfWeek[] /dueendpoint reportsinLearningWindowbased on current time vs path windows
Business rules:
- Creating a lesson auto-creates a
LessonProgressrecord innewstate - Due query excludes mastered lessons and paths not in
activestatus - Domain auto-resolved from project if not provided
Frontend
Routes
/learning— Learning dashboard with due reviews and path listing
Components
LearningPage— Due reviews, path list, stats
Data (hooks)
const { paths, due, stats, recordReview, createPath, createLesson } = useLearning();
Key Interactions
- View lessons due for review with priority ordering
- Record reviews with quality rating (0-5 scale)
- Track mastery progression across learning paths
- Check if currently in a preferred learning time window
- View path completion stats (mastered/reviewing/learning/new counts)
Implementation Phase
Phase 3 (Growth Features) — LearningModule, SM-2 engine, verification queries.