Files
emba-course-solver/CHANGELOG.md
T
Bill cb49123930 v1.3.1: Exhaustive decision-tree search + UX refinements
The v1.3.0 saturation termination silently capped the search after only
the heuristic-favored part of the tree, leaving most per-set ceiling cells
stuck at "0 specs" and hiding genuinely-feasible 3-spec plans in
maximize-count mode. Replace with full exhaustive enumeration plus a
batch of UX refinements that emerged during testing.

Algorithm:

- Drop the saturation early-termination entirely. Search now runs the
  full open-set cartesian product to completion; the iteration cap is
  also removed so no scenario exits partial.
- Add mode-dependent DFS child ordering: priority-order keeps the
  priority-target-first heuristic; maximize-count orders children by
  descending count of qualifications for reachable specs (generalist
  courses tried first).
- Make the (count, priorityScore) comparator mode-aware: priority-order
  ranks by (priorityScore, count) so the user's top spec surfaces;
  maximize-count ranks by (count, priorityScore) so the highest count
  wins. The same rule drives both top-K position and per-cell ceiling
  selection (and the Recommended badge).
- Add an evaluated boolean to each ChoiceOutcome and set it on first
  leaf evaluation. Distinguishes "still searching" from "evaluated, no
  specs achieved" so the UI never shows misleading 0 specs for a cell
  the search hasn't reached yet.
- Throttled progress events (~100ms) carrying iterations / total leaf
  count, drive both the per-set spinner and the global progress bar.

UI:

- Top Plans header shows a horizontal progress bar with
  "iterations / total · NN%" while the search runs; collapses to
  "Search complete · N explored" on completion.
- Per-set spinner next to each elective set heading while any choice
  in that set is unevaluated.
- Per-cell pulsing dot + "searching" text for unevaluated cells.
- Replace the "(HCR, BNK, ...)" text labels on each course with
  color-coded SpecTag pills using a new fixed per-spec palette
  (app/src/data/specColors.ts). Same palette applied to the Top Plans
  achievement badges so the two views are visually consistent.
- "Top outcome if picked ↓" caption above the right side of each open
  elective set so the spec tags are clearly identified as decision-tree
  outcomes (not the course's own qualifications).
- Recommended badge moved inline next to the course name (instead of
  on a separate row below) to keep button heights stable.

Tests:

- Replace the saturation early-termination test with an exhaustion test
  asserting every cell ends with evaluated: true and partial: false.
- Add mode-dependent ordering test (max-count visits Climate Finance
  before Corporate Governance in fall3).
- Add evaluated-flag transition test.
- Add throttled progress-event test (>= ~100ms between consecutive
  emits).
- Performance smoke updated to a 60s budget for the exhaustive
  user-scenario search; 8-open-set typical case completes in ~7s.

Files: solver/decisionTree.ts, solver/priority.ts (already shipped),
data/specColors.ts (new), components/{TopPlans,CourseSelection}.tsx,
state/appState.ts, workers/decisionTree.worker.ts,
__tests__/searchDecisionTree.test.ts, vite.config.ts, CHANGELOG.md,
openspec/changes/decision-tree-exhaustive-search/* (full change spec).
2026-05-09 15:47:56 -04:00

9.2 KiB

Changelog

v1.3.1 — 2026-05-09

Changes

  • Exhaustive decision-tree search — replaced the saturation early-termination with full enumeration of the open-set cartesian product. Per-set ceiling cells now reflect the true best outcome for every (set, course) pair instead of leaving most cells stuck at "0 specs". Top Plans surfaces all genuinely-feasible plans, including 3-spec maximize-count plans that the v1.3.0 search missed. The previous iteration cap has been removed; search runs to full completion.
  • Mode-dependent enumeration ordering — priority-order mode keeps the priority-target-first heuristic; maximize-count mode now orders DFS children by descending count of qualifications for reachable specializations, surfacing generalist courses (e.g., Climate Finance with 6 qualifications) before specialists.
  • Mode-aware comparator — top-K and per-cell ceiling rankings now match the active mode: priority-order ranks by (priorityScore, count) so the top-priority spec surfaces; maximize-count ranks by (count, priorityScore) so the highest count wins. Recommended badges follow the same rule.
  • "Recommended" badge per set — each elective set now highlights the choice with the best ceiling outcome under the current mode. Rendered inline next to the course name to keep button height stable.
  • Color-coded spec tags — the per-cell outcome list and the Top Plans badges now use a fixed per-spec color palette so each specialization is visually identifiable at a glance.
  • "Top outcome if picked ↓" caption — added a small column header on each open elective set so the spec tags are clearly identified as decision-tree outcomes (not the course's own qualifications).
  • Visual progress bar — Top Plans header now shows a progress bar with iterations / total · NN% while the search runs, replacing the earlier text-only count.
  • Per-cell streaming indicators — courses that haven't been evaluated yet show a "searching" pulse instead of misleading "0 specs"; cells transition to their final value as the search completes.
  • Per-set spinner — each elective set heading shows a spinner while at least one of its choices is still unevaluated.

v1.3.0 — 2026-05-09

Changes

  • Top Plans panel — new ranked list of up to 10 complete course plans, each showing the achieved specializations and the courses to pin. An "Adopt plan" button pins all of a plan's courses in one click. Updates progressively as the search finds better outcomes.
  • Priority-aware decision tree — fixes the bug where a specialization could show "Achievable" without any per-set ceiling cell surfacing it. The decision-tree search now compares enumerated combinations by (count desc, priority score desc) and reorders DFS children so courses qualifying for the user's first reachable ranked spec are tried first, surfacing high-priority outcomes early.
  • Bounded search with saturation termination — search stops when the top-K stabilizes (default 500 stable iterations) or when the iteration cap (10000) is hit; partial results are flagged in the UI.
  • Per-cell streaming — the worker now emits per-cell ceiling updates instead of per-set rollups, so the per-set table refines progressively rather than appearing in coarse chunks.

v1.2.2 — 2026-05-09

Changes

  • Healthcare specialization (HCR) — added 15th specialization, Healthcare; qualifies via The Business of Health & Medical Care (Spring Set 2), Analytics & Machine Learning for Managers (Spring Set 3), Digital Marketing Strategy in Practice (Summer Set 2), and Managing Change (Fall Set 1); 10 total credits available, no required course gate
  • Course rename — "Social Media and Mobile Technology" renamed to "Digital Marketing Strategy in Practice"; description replaced with new MSKCC-anchored content covering digital strategy and agentic AI; instructor cleared pending confirmation
  • Cancellations (Approach B) — switched from delete-and-replace to flagging cancelled courses with cancelled: true. "Customer Insights" (Spring Set 5) is now marked cancelled. "Managing Growing Companies" reappears in Summer Set 2 as a cancelled placeholder per the J27 sheet
  • Reachability testdata.test.ts now excludes cancelled courses when counting per-spec set reachability, so future cancellations are caught by an obvious assertion failure

v1.2.1 — 2026-03-27

Bug Fixes

  • Achievable status accuracy — specializations marked "Achievable" are now verified via LP feasibility check against already-achieved specs; previously, a specialization could show "Achievable" based on raw credit potential while actually being infeasible due to credit sharing with higher-priority achieved specializations

v1.2.0 — 2026-03-27

Changes

  • Course info popovers — each course now has an info icon that opens a popover showing the course description, instructor(s), and specialization tags, extracted from the J27 Electives PDF; opens on hover (desktop) or tap (mobile), with smart positioning that flips above when near the bottom of the viewport
  • Page title and favicon — updated browser tab from "app" with Vite icon to "EMBA Specialization Solver" with a graduation cap favicon in NYU Stern purple
  • Viewport-fitted layout — desktop layout now fits within the viewable area without page-level scrolling; each pane scrolls independently

v1.1.1 — 2026-03-27

Changes

  • Course replacement — replaced cancelled "Managing Growing Companies" with new course "Innovation and Design" in Summer Elective Set 2; qualifies for Brand Management, Entrepreneurship and Innovation, Marketing, and Strategy (S2)

v1.1.0 — 2026-03-13

Changes

  • Cancelled course support — "Managing Growing Companies" (Summer Elective Set 2) is marked as cancelled and rendered with strikethrough, greyed-out styling, and a "(Cancelled)" label; it is excluded from solver computations and decision tree enumeration
  • Duplicate course prevention — courses that appear in multiple elective sets (e.g., "Global Immersion Experience II" in Spring Set 1 and Summer Set 1, "The Financial Services Industry" in Spring Set 2 and Fall Set 4) are now linked; selecting one automatically disables and excludes its duplicate from selection and solver calculations, shown with an "(Already selected)" label
  • Credit bar tick marks — specialization progress bars now display light vertical tick marks at 2.5-credit intervals for visual scale reference, layered above bar fills with the 9.0 threshold marker remaining visually distinct

v1.0.0 — 2026-02-28

Initial release of the EMBA Specialization Solver.

Features

  • Optimization engine — LP-based credit allocation solver with two modes:
    • Maximize Count — finds the largest feasible set of specializations, using ranking as tiebreaker
    • Priority Order — greedily adds specializations in user-ranked order
  • Course selection UI — select one course per elective set across 12 sets (Spring, Summer, Fall terms)
  • Drag-and-drop specialization ranking — reorder the 14 specializations by priority with touch and keyboard support
  • Decision tree analysis — Web Worker enumerates remaining course combinations to compute ceiling outcomes per choice
  • Status tracking — each specialization classified as achieved, achievable, missing required course, or unreachable
  • Mode comparison — displays what the alternative optimization mode would produce
  • Credit bars and allocation breakdowns — visual progress toward the 9-credit threshold with expandable per-course detail
  • Credit legend — collapsible explainer for bars, badges, and limits
  • Required course labels — courses that are prerequisites for a specialization show "Required for ..." labels
  • Algorithm explanations — clear descriptions of how each optimization mode works
  • Skeleton loading — placeholder UI while decision tree analysis runs
  • Auto-expand achieved specializations — achieved specs show their credit breakdown by default
  • Responsive layout — two-panel grid on desktop/tablet, single-column on mobile
  • Mobile floating banners — top banner summarizes specialization statuses, bottom banner shows selection progress (N/12); both appear via IntersectionObserver and scroll to their sections on tap
  • CSS transitions and animations — cross-fade course pin/unpin, credit bar width changes, status badge color transitions, expand/collapse panels, mode toggle switching, flash on status changes; all respect prefers-reduced-motion
  • State persistence — rankings and selections saved to localStorage
  • Docker deployment — multi-stage Dockerfile (Node 22 build → Nginx Alpine serve) with Docker Compose, gzip compression, SPA fallback routing, immutable cache headers for hashed assets, configurable port (default 8080)
  • Full test suite — data integrity, feasibility solver, optimizer, and decision tree tests via Vitest

Constraints Modeled

  • Credit non-duplication (2.5 credits per course shared across specializations)
  • Maximum 3 specializations (30 total credits, 9 required each)
  • Required course prerequisites for 4 specializations
  • Strategy S1/S2 tier system (at most 1 S2 course contributes to Strategy)
  • Mutual exclusion from same-set conflicts