Files
Bill 4d6f81d1e5 v1.2.2: Add Healthcare specialization, mark cancelled courses, rename Digital Marketing
Apply the J27 (5/6/2026) Stern specialization sheet:

- Add Healthcare (HCR) as the 15th specialization, with HCR cross-listings on
  spr2-health-medical, spr3-analytics-ml, sum2-social-media (renamed), and
  fall1-managing-change. 10 credits available, no required-course gate.
- Rename sum2-social-media to "Digital Marketing Strategy in Practice";
  replace its description with new MSKCC-anchored content; clear instructor
  pending confirmation of new lead.
- Switch from delete-and-replace to the previously-unused cancelled flag
  (Approach B): mark spr5-customer-insights cancelled, add Managing Growing
  Companies back to Summer Set 2 as a cancelled placeholder per the printed
  sheet.
- Update data integrity tests: course count 46 -> 47, spec count 14 -> 15;
  per-spec "across sets" helper now filters cancelled courses so future
  cancellations trigger an obvious assertion failure (BRM 6 -> 5,
  MKT 7 -> 6, HCR 4 new).
- Replace hardcoded 14 in optimizer.test.ts with SPECIALIZATIONS.length.
2026-05-09 14:50:26 -04:00

6.6 KiB
Raw Permalink Blame History

Context

The Stern J27 Specializations one-pager (5/6/2026) introduces structural changes that go beyond a simple data refresh:

  • A new Healthcare specialization (HCR) — the first new specialization since the app's initial 14
  • Two cancelled-course bookkeeping items (Customer Insights becomes cancelled; Managing Growing Companies reappears as a cancelled placeholder)
  • A renamed elective (Social Media and Mobile Technology → Digital Marketing Strategy in Practice) with a substantively different syllabus, instructor lineup, and a new qualification (Healthcare)

The existing codebase already includes the full plumbing for cancelled: true (defined in app/src/data/types.ts:22, indexed in app/src/data/lookups.ts:43-45, excluded from solver via app/src/state/appState.ts:94-95, greyed-out in app/src/components/CourseSelection.tsx:279) but the prior change replace-cancelled-course-with-innovation-design chose hard-deletion over the flag. This change formalizes the flag as the standing pattern.

Goals / Non-Goals

Goals:

  • Bring data files into exact correspondence with the J27 sheet
  • Establish cancelled: true as the canonical pattern for cancelled courses (Approach B)
  • Make the data integrity test reflect reachable credits (excluding cancelled courses), so that a future cancellation triggers an obviously-failing reachability assertion
  • Verify the published per-spec credit totals from the CSV match the computed reachability table

Non-Goals:

  • No changes to the solver, lookups infrastructure, or React components — the cancelled flag is already honored end-to-end
  • No new color/iconography work for HCR beyond what falls out of the existing rendering of unknown specializations (if a missing color is observed during browser testing, address with a follow-up; do not block on it)
  • No data-migration support for older saved selections — the app does not persist user state across reloads
  • No support for multiple simultaneous cohorts; this is an in-place J27 update

Decisions

Approach B (cancelled flag), not hard-delete

Use cancelled: true rather than removing entries. The flag exists, is fully wired, and matches the printed sheet 1:1 (which preserves the slot even when a course is cancelled). The prior delete-and-replace pattern was driven by lack of UI greying — that's no longer a constraint.

Alternatives considered: Hard-delete the cancelled entries, as in replace-cancelled-course-with-innovation-design. Rejected because the school's official sheet shows the cancelled slot, and preserving slot ordering helps students cross-reference printed materials.

Add sum2-managing-growing-companies as a fresh cancelled entry

Even though a previous change removed this id, the J27 sheet reintroduces it as a cancelled placeholder. We add it back with cancelled: true and empty qualifications. The id is reusable because no persisted state references it.

Alternative considered: Skip it (Summer Set 2 stays at 4 entries). Rejected because the printed sheet shows 5 slots; hiding one would create a discrepancy the user might flag as a bug.

Update reachability test to exclude cancelled courses

Modify data.test.ts so the per-spec "across sets" assertion filters out qualifications belonging to cancelled courses before counting distinct sets. This matches the CSV's published credit totals (BRM 12.5 = 5 sets × 2.5; MKT 15.0 = 6 sets × 2.5; HCR 10.0 = 4 sets × 2.5).

Alternative considered: Leave the test counting cancelled courses and accept that BRM/MKT reach-counts disagree with the published totals. Rejected — the test's stated purpose is to mirror the reachability table, and divergence makes regressions invisible.

Do NOT change coursesBySpec to filter cancelled

The lookup map keeps cancelled qualifications. The solver already excludes them via appState's excluded set, and other consumers (or future debug tooling) may want the full picture. Filter at the consumer (test), not at the source.

Alternative considered: Strip cancelled entries from coursesBySpec directly. Rejected because that hides data from any future caller that might legitimately want to inspect cancelled courses, and the test is the only consumer that currently cares.

Clear instructor for Digital Marketing course

The new description (digital-marketing.txt) describes a substantively different course (MSKCC engagement, agentic AI) led by guest contributors from L'Oréal and Google Gemini, with no clear primary instructor named. Set instructors: [] rather than carry forward Stewart Krentzman from the old syllabus, which would be misleading.

Alternative considered: Retain the prior instructor name. Rejected — the course content has changed materially, and showing a stale instructor is worse than showing none.

Healthcare gets no required-course gate

The CSV asterisk convention (used for required courses) does not appear on any HCR-qualifying course. Healthcare therefore has no requiredCourseId.

Risks / Trade-offs

  • Reachability test now depends on cancelled flag → Mitigation: the test continues to assert all 14 (now 15) specs; if the cancelled flag is accidentally cleared, the test's set count for BRM/MKT will jump back up and fail
  • HCR may render with no themed color in legend → Mitigation: verify in browser; if a default color is unacceptable, file a follow-up rather than blocking this change
  • Reusing the sum2-managing-growing-companies id → Risk is low (no persistence); document the reuse in the changelog so a future bisecting developer is not surprised
  • CSV header dates the sheet 5/6/2026 (one day before today's date) → No risk; just confirms the sheet is current

Migration Plan

  1. Land data changes in a single commit (or one commit per file, whichever fits the repo's PR style)
  2. Run pnpm test (or npm test) and confirm all data integrity tests pass with updated expectations
  3. Browser-verify: load the app, observe HCR appears in the specialization list, the two cancelled courses render greyed, the renamed Digital Marketing course shows the new description on info-popover hover
  4. Bump __APP_VERSION__ to 1.2.2 (patch bump consistent with prior data-only updates) and __APP_VERSION_DATE__ in app/vite.config.ts
  5. Add a 1.2.2 entry to CHANGELOG.md

Rollback: revert the data file changes; no schema or build changes to undo.

Open Questions

  • Lead instructor for Digital Marketing Strategy in Practice — the description names guest speakers but no primary instructor; clear for now and refresh if the school publishes one
  • HCR display color/order — verify in browser; address with a follow-up if the default rendering looks wrong