feat: LP catalog + Oxbridge migration + per-module training quiz - #1
Merged
Conversation
New `lesson_plan_catalog` table with polymorphic `source` column for multi-vendor content (oxbridge, taleemabad_core, nbf, beaconhouse, …). Idempotency via unique (source, source_row_id). Also adds scripts/migrate-lesson-plans.py — one-shot Oxbridge migration from Taleemabad fde_production.lesson_plan_externallessonplan (source='oxbridge', 70 active rows). HTML content, no PDFs. Certified counts after migration (verified live via PostgREST): Grade Six: 4, Seven: 12, Eight: 11, Nine: 16, Ten: 5, Eleven: 12, Twelve: 10 Subjects: Biology 13, Chemistry 14, Computer Science 11, General Science 16, Physics 16 Total: 70 (matches source 1:1) Applied to live Supabase via schema_versions v1.0.4. Refs: FEAT-080 (Ramisha), FEAT-059 (Sabeen)
…attempts Kamal on Card #1 flagged: 'we completed the training but cannot access the quiz — legacy NIETE app has a quiz after every training.' Root cause was not migration or routing — the per-module training-quiz code path simply wasn't implemented in NIETE-Rumi (only grand quizzes were). Adds: - startTrainingQuiz(userId, moduleId, phoneNumber) in quiz-delivery.service: filters training_questions by training_module_id, creates attempts with quiz_kind='training_module'. No cooldown, feedback-only grading. - sendQuestion/handleQuizButton/gradeAttempt now branch on quiz_kind. - handleModuleDone in content-delivery.service: counts active questions for the module, fires startTrainingQuiz *fire-and-forget*, then continues to deliverNextModule (non-blocking parallel model per CONTEXT.md's training-quiz spec). - Schema reconcile on training_assessment_attempts: adds quiz_kind (default 'grand') + training_module_id BIGINT + CHECK enforcing exactly one of (grand_quiz_id, training_module_id). Idempotent via ADD COLUMN IF NOT EXISTS + DO block for the constraint. Applied to live Supabase before this commit lands. - tests/training/training-quiz.test.js: 6 tests covering eligibility gate, filter-by-module, fire-and-forget non-blocking, silent-skip when 0 questions. Refs: Card #1 (Kamal — teacher training migration is not fully migrated)
This was referenced Aug 14, 2026
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two independent features on one branch — both flowed from the ICT simulation-week (Jul 14–21) partner conversations.
Commit 1 (7d80a4b) — LP catalog + Oxbridge migration (70 rows)
lesson_plan_catalogwith polymorphicsourcecolumn (`oxbridge`, `taleemabad_core`, `nbf`, `beaconhouse`, …).(source, source_row_id).scripts/migrate-lesson-plans.py— one-shot Oxbridge migration from Taleemabad `fde_production.lesson_plan_externallessonplan` (source='oxbridge', 70 active rows).Commit 2 (2f10117) — per-module training quiz (non-blocking)
startTrainingQuiz(userId, moduleId, phoneNumber)inquiz-delivery.service.js, wires intohandleModuleDoneincontent-delivery.service.js(fire-and-forget parallel — quiz Q1 goes out ahead of next-module video).quiz_kinddiscriminator column + CHECK constraint on `training_assessment_attempts`.Test plan
Refs