## 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