ADR-LMS-PHASE-2: Learning Management System - Advanced Learning Platform
Status: Proposed Date: 2025-12-11 Deciders: Hal Casteel (Founder/CEO/CTO), CODITECT Core Team Technical Story: Evolve the Phase 1 onboarding database into a comprehensive learning platform with adaptive content, skill trees, certification paths, and team learning capabilities
Context and Problem Statement
Phase 1 LMS (ADR-030-lms-phase-1) provides persistent onboarding progress tracking. However, it has limitations:
- Static curriculum - All users follow the same 11-module path
- No adaptive learning - Content doesn't adjust to user skill level
- Limited content types - Only modules and badges, no skill trees
- Single-user focus - No team or organization learning features
- No spaced repetition - No reinforcement of learned concepts
- Basic analytics - Event stream without actionable insights
- No certification - No formal credential or verification system
The Problem: How do we evolve the LMS from onboarding tracker to a comprehensive learning platform that adapts to users, supports teams, and provides verifiable credentials?
Decision Drivers
Technical Requirements
- R1: Adaptive content delivery based on user skill assessment
- R2: Skill tree and dependency graph for learning paths
- R3: Spaced repetition system for knowledge retention
- R4: Team/organization learning management
- R5: Quiz engine with multiple question types
- R6: Certification system with verifiable credentials
- R7: Learning analytics dashboard
- R8: Content versioning and A/B testing
- R9: Integration with external LMS standards (xAPI/SCORM)
User Experience Goals
- UX1: Personalized learning paths based on goals and skill level
- UX2: Visual progress through skill trees
- UX3: Spaced repetition reminders for review
- UX4: Team leaderboards and collaborative learning
- UX5: Downloadable/shareable certificates
Business Requirements
- B1: Support for paid/premium learning content
- B2: Team licensing and seat management
- B3: Analytics for content creators
- B4: Integration with enterprise identity providers
Proposed Solution
Phase 2.1: Adaptive Learning Engine
New Tables:
-- Skill definitions and relationships
CREATE TABLE learning_skills (
id INTEGER PRIMARY KEY AUTOINCREMENT,
skill_key TEXT UNIQUE NOT NULL,
skill_name TEXT NOT NULL,
description TEXT,
category TEXT, -- core, advanced, specialization
parent_skill_id INTEGER, -- For skill hierarchy
difficulty_level INTEGER DEFAULT 1, -- 1-10 scale
estimated_mastery_hours REAL,
icon TEXT,
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (parent_skill_id) REFERENCES learning_skills(id)
);
-- Skill prerequisites (dependency graph)
CREATE TABLE learning_skill_prerequisites (
id INTEGER PRIMARY KEY AUTOINCREMENT,
skill_id INTEGER NOT NULL,
prerequisite_skill_id INTEGER NOT NULL,
required_mastery_level INTEGER DEFAULT 50, -- 0-100
FOREIGN KEY (skill_id) REFERENCES learning_skills(id) ON DELETE CASCADE,
FOREIGN KEY (prerequisite_skill_id) REFERENCES learning_skills(id) ON DELETE CASCADE,
UNIQUE(skill_id, prerequisite_skill_id)
);
-- User skill mastery tracking
CREATE TABLE learning_skill_mastery (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
skill_id INTEGER NOT NULL,
mastery_level INTEGER DEFAULT 0, -- 0-100
confidence_score REAL DEFAULT 0.5, -- Bayesian confidence
last_practiced TEXT,
practice_count INTEGER DEFAULT 0,
streak_days INTEGER DEFAULT 0,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE,
FOREIGN KEY (skill_id) REFERENCES learning_skills(id) ON DELETE CASCADE,
UNIQUE(user_id, skill_id)
);
-- Module to skill mapping
CREATE TABLE learning_module_skills (
id INTEGER PRIMARY KEY AUTOINCREMENT,
module_id INTEGER NOT NULL,
skill_id INTEGER NOT NULL,
teaches_mastery INTEGER DEFAULT 20, -- Mastery points gained
FOREIGN KEY (module_id) REFERENCES learning_modules(id) ON DELETE CASCADE,
FOREIGN KEY (skill_id) REFERENCES learning_skills(id) ON DELETE CASCADE,
UNIQUE(module_id, skill_id)
);
Adaptive Algorithm:
def recommend_next_content(user_id):
"""
Bayesian knowledge tracing algorithm:
1. Get user's current skill mastery levels
2. Find skills with prerequisites satisfied
3. Rank by: (target_mastery - current_mastery) * prerequisite_confidence
4. Select modules teaching top-ranked skills
5. Filter by user's learning style preference
"""
pass
Phase 2.2: Spaced Repetition System
New Tables:
-- Review cards for spaced repetition
CREATE TABLE learning_review_cards (
id INTEGER PRIMARY KEY AUTOINCREMENT,
card_key TEXT UNIQUE NOT NULL,
module_id INTEGER,
skill_id INTEGER,
card_type TEXT NOT NULL, -- concept, quiz, exercise
front_content TEXT NOT NULL, -- Question/prompt
back_content TEXT NOT NULL, -- Answer/explanation
difficulty_rating REAL DEFAULT 0.3, -- 0-1, affects scheduling
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (module_id) REFERENCES learning_modules(id) ON DELETE SET NULL,
FOREIGN KEY (skill_id) REFERENCES learning_skills(id) ON DELETE SET NULL
);
-- User review schedule (SM-2 algorithm)
CREATE TABLE learning_review_schedule (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
card_id INTEGER NOT NULL,
ease_factor REAL DEFAULT 2.5, -- SM-2 ease factor
interval_days INTEGER DEFAULT 1, -- Days until next review
repetitions INTEGER DEFAULT 0, -- Successful repetitions
next_review_date TEXT,
last_review_date TEXT,
last_quality INTEGER, -- 0-5 quality rating
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE,
FOREIGN KEY (card_id) REFERENCES learning_review_cards(id) ON DELETE CASCADE,
UNIQUE(user_id, card_id)
);
SM-2 Algorithm Implementation:
def update_review_schedule(user_id, card_id, quality):
"""
SuperMemo 2 algorithm:
quality: 0-5 (0=blackout, 5=perfect)
if quality >= 3:
if repetitions == 0: interval = 1
elif repetitions == 1: interval = 6
else: interval = round(interval * ease_factor)
repetitions += 1
else:
repetitions = 0
interval = 1
ease_factor = max(1.3, ease_factor + 0.1 - (5-quality)*(0.08+(5-quality)*0.02))
"""
pass
Phase 2.3: Quiz Engine
New Tables:
-- Quiz definitions
CREATE TABLE learning_quizzes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quiz_key TEXT UNIQUE NOT NULL,
module_id INTEGER,
skill_id INTEGER,
title TEXT NOT NULL,
description TEXT,
time_limit_minutes INTEGER,
passing_score INTEGER DEFAULT 70,
max_attempts INTEGER, -- NULL = unlimited
shuffle_questions BOOLEAN DEFAULT 1,
show_answers_after BOOLEAN DEFAULT 1,
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (module_id) REFERENCES learning_modules(id) ON DELETE SET NULL,
FOREIGN KEY (skill_id) REFERENCES learning_skills(id) ON DELETE SET NULL
);
-- Quiz questions with multiple types
CREATE TABLE learning_quiz_questions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
quiz_id INTEGER NOT NULL,
question_type TEXT NOT NULL, -- multiple_choice, true_false, short_answer, code
question_text TEXT NOT NULL,
question_code TEXT, -- For code questions
options TEXT, -- JSON array for multiple choice
correct_answer TEXT NOT NULL, -- Answer or JSON for multiple correct
explanation TEXT, -- Shown after answer
points INTEGER DEFAULT 1,
difficulty INTEGER DEFAULT 1, -- 1-5
sort_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (quiz_id) REFERENCES learning_quizzes(id) ON DELETE CASCADE
);
-- Quiz attempts
CREATE TABLE learning_quiz_attempts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
quiz_id INTEGER NOT NULL,
started_at TEXT DEFAULT CURRENT_TIMESTAMP,
completed_at TEXT,
score INTEGER,
max_score INTEGER,
passed BOOLEAN,
time_spent_seconds INTEGER,
answers TEXT, -- JSON of question_id: user_answer
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE,
FOREIGN KEY (quiz_id) REFERENCES learning_quizzes(id) ON DELETE CASCADE
);
Phase 2.4: Team Learning
New Tables:
-- Organizations
CREATE TABLE learning_organizations (
id INTEGER PRIMARY KEY AUTOINCREMENT,
org_key TEXT UNIQUE NOT NULL,
org_name TEXT NOT NULL,
org_type TEXT, -- company, team, community
license_type TEXT, -- free, pro, enterprise
max_seats INTEGER,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT 1
);
-- Organization membership
CREATE TABLE learning_org_members (
id INTEGER PRIMARY KEY AUTOINCREMENT,
org_id INTEGER NOT NULL,
user_id TEXT NOT NULL,
role TEXT DEFAULT 'member', -- admin, manager, member
joined_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (org_id) REFERENCES learning_organizations(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE,
UNIQUE(org_id, user_id)
);
-- Learning paths (curated sequences)
CREATE TABLE learning_paths (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path_key TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
description TEXT,
org_id INTEGER, -- NULL = public
created_by TEXT,
estimated_hours REAL,
difficulty_level TEXT,
is_public BOOLEAN DEFAULT 0,
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (org_id) REFERENCES learning_organizations(id) ON DELETE SET NULL,
FOREIGN KEY (created_by) REFERENCES learning_users(user_id) ON DELETE SET NULL
);
-- Path modules (ordered sequence)
CREATE TABLE learning_path_modules (
id INTEGER PRIMARY KEY AUTOINCREMENT,
path_id INTEGER NOT NULL,
module_id INTEGER NOT NULL,
sort_order INTEGER NOT NULL,
is_required BOOLEAN DEFAULT 1,
FOREIGN KEY (path_id) REFERENCES learning_paths(id) ON DELETE CASCADE,
FOREIGN KEY (module_id) REFERENCES learning_modules(id) ON DELETE CASCADE
);
-- User path enrollment
CREATE TABLE learning_path_enrollments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
path_id INTEGER NOT NULL,
enrolled_at TEXT DEFAULT CURRENT_TIMESTAMP,
completed_at TEXT,
progress_percentage INTEGER DEFAULT 0,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE,
FOREIGN KEY (path_id) REFERENCES learning_paths(id) ON DELETE CASCADE,
UNIQUE(user_id, path_id)
);
Phase 2.5: Certification System
New Tables:
-- Certificate definitions
CREATE TABLE learning_certificates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
cert_key TEXT UNIQUE NOT NULL,
title TEXT NOT NULL,
description TEXT,
cert_level TEXT, -- foundational, professional, expert
required_path_id INTEGER, -- Path that grants this cert
required_quiz_id INTEGER, -- Final exam
required_score INTEGER DEFAULT 80,
validity_months INTEGER, -- NULL = never expires
badge_id INTEGER, -- Associated badge
is_active BOOLEAN DEFAULT 1,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (required_path_id) REFERENCES learning_paths(id) ON DELETE SET NULL,
FOREIGN KEY (required_quiz_id) REFERENCES learning_quizzes(id) ON DELETE SET NULL,
FOREIGN KEY (badge_id) REFERENCES learning_badges(id) ON DELETE SET NULL
);
-- Issued certificates
CREATE TABLE learning_issued_certificates (
id INTEGER PRIMARY KEY AUTOINCREMENT,
certificate_id INTEGER NOT NULL,
user_id TEXT NOT NULL,
issued_at TEXT DEFAULT CURRENT_TIMESTAMP,
expires_at TEXT,
verification_code TEXT UNIQUE NOT NULL, -- UUID for verification
final_score INTEGER,
metadata TEXT, -- JSON additional data
is_revoked BOOLEAN DEFAULT 0,
FOREIGN KEY (certificate_id) REFERENCES learning_certificates(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE
);
Verification Endpoint:
def verify_certificate(verification_code):
"""
Returns certificate details if valid:
- Holder name
- Certificate title
- Issue date
- Expiration status
- Verification URL
"""
pass
Phase 2.6: Analytics Dashboard
New Tables:
-- Aggregated analytics (computed daily)
CREATE TABLE learning_analytics_daily (
id INTEGER PRIMARY KEY AUTOINCREMENT,
date TEXT NOT NULL,
org_id INTEGER, -- NULL = platform-wide
metric_name TEXT NOT NULL,
metric_value REAL NOT NULL,
dimension TEXT, -- For grouping (skill, module, etc.)
dimension_value TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
UNIQUE(date, org_id, metric_name, dimension, dimension_value)
);
-- Funnel tracking
CREATE TABLE learning_funnels (
id INTEGER PRIMARY KEY AUTOINCREMENT,
funnel_key TEXT UNIQUE NOT NULL,
funnel_name TEXT NOT NULL,
steps TEXT NOT NULL, -- JSON array of step definitions
created_at TEXT DEFAULT CURRENT_TIMESTAMP
);
-- Funnel step completions
CREATE TABLE learning_funnel_events (
id INTEGER PRIMARY KEY AUTOINCREMENT,
funnel_id INTEGER NOT NULL,
user_id TEXT NOT NULL,
step_index INTEGER NOT NULL,
step_name TEXT NOT NULL,
completed_at TEXT DEFAULT CURRENT_TIMESTAMP,
time_from_previous_seconds INTEGER,
FOREIGN KEY (funnel_id) REFERENCES learning_funnels(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES learning_users(user_id) ON DELETE CASCADE
);
Key Metrics:
- Daily/Weekly/Monthly Active Learners (DAL/WAL/MAL)
- Module completion rates
- Quiz pass rates
- Average time to certification
- Skill mastery distribution
- Review retention rates
- Path completion funnels
New /cxq Commands (Phase 2)
# Skill tree queries
/cxq --skills # List all skills
/cxq --skill-tree # Visual skill tree
/cxq --skill-mastery # User's skill levels
/cxq --skill-recommendations # Recommended skills to learn
# Spaced repetition
/cxq --review-due # Cards due for review
/cxq --review-stats # Review statistics
/cxq --review-schedule # Upcoming review schedule
# Quiz management
/cxq --quizzes # Available quizzes
/cxq --quiz-history # Past quiz attempts
/cxq --quiz-analytics # Quiz performance analytics
# Team learning
/cxq --team-progress # Team progress dashboard
/cxq --team-leaderboard # Team rankings
/cxq --team-paths # Assigned learning paths
# Certification
/cxq --certificates # Available certifications
/cxq --my-certs # User's certificates
/cxq --verify-cert CODE # Verify certificate
# Analytics
/cxq --learning-dashboard # Full analytics dashboard
/cxq --learning-trends # Progress trends over time
Migration Strategy
Phase 2.1 Migration (Adaptive Learning)
-- Add new tables
-- Populate learning_skills from existing categories
-- Map existing modules to skills
-- Initialize skill_mastery from completed modules
Phase 2.2 Migration (Spaced Repetition)
-- Add review tables
-- Generate initial cards from module content
-- No existing data to migrate
Phase 2.3 Migration (Quiz Engine)
-- Add quiz tables
-- Convert existing has_quiz modules to full quizzes
-- Migrate quiz_score data to quiz_attempts
Backward Compatibility
- All Phase 1 queries continue to work
- New features are additive
- Existing progress data preserved
Implementation Roadmap
| Sub-Phase | Features | Estimated Effort | Dependencies |
|---|---|---|---|
| 2.1 | Adaptive Learning Engine | 2 weeks | Phase 1 complete |
| 2.2 | Spaced Repetition | 1 week | 2.1 |
| 2.3 | Quiz Engine | 2 weeks | 2.1 |
| 2.4 | Team Learning | 2 weeks | 2.1 |
| 2.5 | Certification System | 1 week | 2.3, 2.4 |
| 2.6 | Analytics Dashboard | 2 weeks | All above |
Total Estimated Effort: 10 weeks
Alternatives Considered
Alternative 1: External LMS Integration
Description: Use existing LMS (Moodle, Canvas, etc.)
Pros:
- Full-featured out of box
- Industry standard compliance
- Existing ecosystem
Cons:
- External dependency
- Doesn't integrate with /cxq
- Overkill for CLI tool learning
- Licensing costs
Decision: Rejected - lose integration benefits
Alternative 2: Third-Party API (Coursera, Udemy)
Description: Integrate with learning content platforms
Pros:
- Professional content
- Recognized credentials
- Large content library
Cons:
- Doesn't teach CODITECT specifically
- External dependency
- Per-seat costs
- No CLI integration
Decision: Rejected - need CODITECT-specific content
Success Metrics
| Metric | Target | Measurement |
|---|---|---|
| Skill mastery improvement | +20% avg mastery | Before/after comparison |
| Knowledge retention | 80% after 30 days | Spaced repetition success rate |
| Quiz pass rate | >70% first attempt | Quiz analytics |
| Path completion rate | >60% | Funnel analytics |
| Certification rate | >40% of active users | Certificate issuance |
| Team adoption | >5 orgs in first quarter | Org registrations |
Related Documents
- ADR-030-lms-phase-1.md - Current Phase 1 implementation
- LMS-DATABASE-SCHEMA.md - Phase 1 schema
- USER-TRAINING-PATHWAYS.md - Training curriculum
- ADR-021-context-query.md - Parent query system
Open Questions
-
Content Authoring: How will new modules/quizzes be authored?
- Option A: Markdown files with frontmatter
- Option B: Admin CLI commands
- Option C: Web-based editor
-
External Identity: Should we support OAuth/SAML for teams?
- Consideration: Enterprise customers may require SSO
-
xAPI/SCORM: Is LRS integration needed for enterprise?
- Consideration: Some enterprises require xAPI statements
-
Offline Support: How to handle review cards offline?
- Consideration: Mobile/disconnected scenarios
Status: Proposed - Awaiting prioritization Last Updated: 2025-12-11 Version: 0.1.0 (Draft)