Files
emba-course-solver/openspec/changes/show-completed-plan/proposal.md
T
Bill cb2024f857 v1.5.1: Show completed plan in Top Plans
Once every elective set is pinned, the Top Plans panel now renders the
user's completed selection as a single "Your Plan" card showing the
achievement count and pinned courses. Previously the panel went blank
because the all-pinned branch in useAppState cleared topPlans, even
though the spec strip was already showing the achievement.

Synthesizes a single PlanOutcome from pinnedAssignments +
optimizationResult.achieved + the priority scorer; TopPlans detects the
all-pinned state via ELECTIVE_SETS.every(...) and bypasses the
length>0 filter so a 0-spec completed plan still renders honestly.
2026-05-10 11:57:56 -04:00

2.4 KiB

Why

When a student pins a course in every elective set, the Top Plans panel goes blank and shows the placeholder "No plans yet achieve a specialization with the current pinned courses." This is misleading: the optimizer has already computed achievement (visible in the spec strip), but the Top Plans state is short-circuited to [] because no decision-tree search runs when there are no open sets. The student's completed plan IS the only plan — it should be the one rendered.

What Changes

  • When openSetIds.length === 0, synthesize a single PlanOutcome from the pinned assignments + optimizationResult.achieved + the priority scorer, and surface it through the existing topPlans state slice instead of clearing the slice.
  • Render the synthesized plan unconditionally (no achievedSpecs.length > 0 filter) so a 0-spec completed plan still shows the courses-and-zero-achievements summary rather than the search placeholder.
  • Header copy switches to "Your Plan" (singular) when openSetIds.length === 0. Otherwise stays "Top Plans".
  • Leaf cache, search progress strip, "ranked by specs achieved" subtitle, and the search-complete/incomplete static text remain unchanged.

Capabilities

New Capabilities

None.

Modified Capabilities

  • optimization-engine: when all elective sets are pinned, useAppState SHALL emit a single synthesized PlanOutcome rather than clearing the top-K slice.
  • unified-specialization-panel: the Top Plans panel SHALL render a synthesized completed plan with header copy "Your Plan" and SHALL NOT filter out a single completed plan with zero achievements.

Impact

  • app/src/state/appState.ts — replace the setTopPlans([]) early return with a synthesized one-element top-K when openSetIds.length === 0. Use makePriorityScorer(state.ranking)(achieved) for the score.
  • app/src/components/TopPlans.tsx — when plans.length === 1 and the only plan's courseAssignments covers every elective set, render it as "Your Plan" (header copy). Drop the length > 0 visibility filter for that single-plan case so a 0-spec completed plan still renders. Other rendering paths unchanged.
  • No new tests strictly required, but a state-layer assertion for the synthesis would be nice. Existing 97 tests must continue to pass.
  • app/vite.config.ts — patch version bump (e.g., 1.5.1).
  • CHANGELOG.md — release entry.
  • No data-file changes.