Problem
semester is a hardcoded free-text 'Spring 2026' default, not a real system. It's threaded through the analytics/gradebook tables but there's no term entity, no validation, and enrollment isn't semester-scoped.
Where it lives today:
courses.semester — TEXT DEFAULT 'Spring 2026', on the shared catalog (backend/db/migrations/0001_baseline_schema.sql:37)course_concept_stats.semester — NOT NULL DEFAULT 'Spring 2026', part of UNIQUE(course_id, concept_name, semester) (:211, :221)course_summary.semester — NOT NULL DEFAULT 'Spring 2026', part of PRIMARY KEY(course_id, semester) (:227, :235)backend/routes/gradebook.py filters/returns it (:48-57, :99, :154); backend/services/course_context_service.py reads/writes it, defaulting to 'Spring 2026'
Gaps
- Enrollment isn't semester-scoped.
user_courses has no semester column (0001_baseline_schema.sql:48-58). Semester lives only on the shared courses row, so "CS101 Spring" vs "CS101 Fall" must be two separate catalog rows. - The courses API drops semester.
/api/graph/<user>/courses (getCourses) doesn't return it — flagged in docs/gradebook-rollout-notes.md:52,69. - No term model. No semester entity, no validation, no concept of the "current/active term" — just a
'Spring 2026' string copy-pasted across four places.
Proposed
Related
Pairs with the frontend integration issue (see cross-link below). Touches knowledge-graph course scoping and the gradebook.
Related
Frontend counterpart: #260
Problem
semesteris a hardcoded free-text'Spring 2026'default, not a real system. It's threaded through the analytics/gradebook tables but there's no term entity, no validation, and enrollment isn't semester-scoped.Where it lives today:
courses.semester—TEXT DEFAULT 'Spring 2026', on the shared catalog (backend/db/migrations/0001_baseline_schema.sql:37)course_concept_stats.semester—NOT NULL DEFAULT 'Spring 2026', part ofUNIQUE(course_id, concept_name, semester)(:211,:221)course_summary.semester—NOT NULL DEFAULT 'Spring 2026', part ofPRIMARY KEY(course_id, semester)(:227,:235)backend/routes/gradebook.pyfilters/returns it (:48-57,:99,:154);backend/services/course_context_service.pyreads/writes it, defaulting to'Spring 2026'Gaps
user_courseshas nosemestercolumn (0001_baseline_schema.sql:48-58). Semester lives only on the sharedcoursesrow, so "CS101 Spring" vs "CS101 Fall" must be two separate catalog rows./api/graph/<user>/courses(getCourses) doesn't return it — flagged indocs/gradebook-rollout-notes.md:52,69.'Spring 2026'string copy-pasted across four places.Proposed
user_courses.semester(or otherwise scope enrollment to a term).semesterin/api/graph/<user>/coursesand any course-listing API.'Spring 2026'default with the term model.Related
Pairs with the frontend integration issue (see cross-link below). Touches knowledge-graph course scoping and the gradebook.
Related
Frontend counterpart: #260