4d6f81d1e5
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.
76 lines
6.6 KiB
Markdown
76 lines
6.6 KiB
Markdown
## 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
|