Commit Graph

11 Commits

Author SHA1 Message Date
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
Bill 4b80fac500 v1.3.0: Streamed top-K decision-tree plans + priority-aware ceiling
Fixes the bug where a specialization could show "Achievable" while no
per-set ceiling cell surfaces a path to it. Reproduction: pin SP2=Business
of Health & Medical Care, SP4=Foundations of Fintech, SP5=Corporate Finance,
SE1=GIE; rank HCR first. Healthcare showed Achievable but every ceiling
cell excluded HCR.

Root cause: computeCeiling used strict > on count alone, so the first
equal-count combination found won permanently and HCR-including outcomes
were never recorded.

Changes:

- Replace per-(set, choice) computeCeiling loop with a single full-tree
  searchDecisionTree DFS. Both the per-set ceiling table and a new ranked
  top-K plan list (default K=10) are populated from one enumeration.
- Comparison rule everywhere is (count desc, priority score desc,
  deterministic-tiebreak). priorityScore extracted from optimizer.ts
  into a shared priority.ts module used by both call sites.
- Heuristic enumeration ordering: select the first reachable ranked spec
  as priorityTarget; reorder DFS children at every level so target-
  qualifying courses are tried first. High-priority outcomes surface in
  early iterations instead of being blocked by less-relevant equal-count
  results.
- Bounded search: terminate on saturation (top-K stable for 500
  iterations) or hard cap (10000 iterations); set partial=true if cap
  hit. Mitigates the worst-case enumeration cost.
- Worker protocol: tagged-union response with topKUpdate, choiceUpdate
  (per-cell, replaces per-set setComplete), and allComplete events.
- App state adds topPlans/topPlansPartial slices and an adoptPlan action
  that pins a plan's full course assignment in one click. Also fixes
  loadState's stale "ranking.length !== 14" check (now uses
  SPECIALIZATIONS.length so HCR-era saved state restores correctly).
- New TopPlans component renders the ranked list with adopt buttons,
  placed above CourseSelection in the right column.
- 17 new tests in searchDecisionTree.test.ts covering priority scoring,
  bounded ranked list, comparison rule, target selection, the user's
  reproduction scenario, streaming monotonicity, saturation termination,
  and a performance smoke test (< 5s for the 8-open-set case).
- Existing decisionTree.test.ts: one test amended for per-cell streaming
  semantics; remaining 3 unchanged and passing.
2026-05-09 14:51:32 -04:00
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
Bill 0beafb58b5 Add design docs for achievable status fix and course description popups change artifacts 2026-03-27 19:54:14 -04:00
Bill 99a39a2581 v1.1.1: Replace cancelled Managing Growing Companies with Innovation and Design
Replace cancelled course in Summer Elective Set 2 with new course
"Innovation and Design" qualifying for Brand Management, Entrepreneurship
and Innovation, Marketing, and Strategy (S2).
2026-03-27 11:26:53 -04:00
Bill 663d70e44b Add Docker Compose deployment with multi-stage build and nginx
Multi-stage Dockerfile builds the Vite app in Node 22 and serves static
assets from nginx:alpine. Includes gzip compression, SPA fallback routing,
immutable cache headers for hashed assets, and configurable port mapping
(default 8080). Deploy with `docker compose up -d`.
2026-02-28 23:01:50 -05:00
Bill 7a8330e205 Add CSS transitions and animations for smooth UI interactions
Animate course set pin/unpin with cross-fade content swap, credit bar
width changes, status badge color transitions, expand/collapse panels
(CreditLegend, AllocationBreakdown), mode toggle switching, and
ModeComparison banner fade. Specialization rows flash on credit/status
changes. Threshold markers animate position. All animations respect
prefers-reduced-motion.
2026-02-28 22:46:11 -05:00
Bill 7940050196 Add mobile floating banners for specialization status and course selection progress
On mobile, the single-column layout makes it easy to lose context when
scrolling between the specializations and course selection panels. This adds
two floating banners that appear via IntersectionObserver:

- Top banner: summarizes specialization statuses (achieved/achievable/missing/unreachable)
- Bottom banner: shows course selection progress (N/12 selected)

Both slide in/out with CSS transitions and scroll to their respective
sections on tap. Only rendered on mobile viewports (max-width: 639px).
2026-02-28 22:27:07 -05:00
Bill 969d4ff5a9 Improve analysis UX: algorithm explanations, skeleton loading, auto-expand achieved specs
- Replace terse one-line optimization mode descriptions with clearer multi-sentence
  explanations of how Maximize Count and Priority Order algorithms behave
- Add skeleton loading placeholders on course buttons while analysis is pending
- Auto-expand achieved specializations to show credit breakdown by default
- Add instructional subtitles to Course Selection and Specializations sections
- Make Clear and Clear All buttons more prominent with visible backgrounds
2026-02-28 21:56:06 -05:00
Bill f8bab9ee33 UI improvements: responsive layout, unified panels, credit legend
- Add responsive 2-panel layout (mobile single-col, tablet/desktop grid)
- Unify specialization ranking with credit bars, status badges, and
  expandable allocation breakdowns (remove standalone ResultsDashboard)
- Inline decision tree ceiling data on course buttons with spec counts
- Add Clear All button to reset all course selections
- Add collapsible CreditLegend explaining bars, badges, and limits
- Extract ModeComparison and MutualExclusionWarnings to Notifications
- Add useMediaQuery hook with matchMedia-based breakpoint detection
2026-02-28 21:17:50 -05:00
Bill 9e00901179 Implement EMBA Specialization Solver web app
Full React+TypeScript app with LP-based optimization engine,
drag-and-drop specialization ranking (with touch/arrow support),
course selection UI, results dashboard with decision tree, and
two optimization modes (maximize-count, priority-order).
2026-02-28 20:43:00 -05:00