@@ -216,6 +216,8 @@ def cmd_evaluate(args: argparse.Namespace) -> None:
216216
217217def cmd_match (args : argparse .Namespace ) -> None :
218218 """Match prerequisites against specific programs."""
219+ from core .lr_predictor import predict_prob_full
220+
219221 profile = load_profile (args .profile )
220222 programs = load_all_programs ()
221223
@@ -225,6 +227,8 @@ def cmd_match(args: argparse.Namespace) -> None:
225227 console .print (f"[red]Program '{ args .program } ' not found.[/red]" )
226228 return
227229
230+ gre_quant = profile .test_scores .gre_quant
231+
228232 console .print ()
229233 console .print (Panel ("Prerequisite Match Report" , border_style = "cyan" ))
230234
@@ -237,6 +241,17 @@ def cmd_match(args: argparse.Namespace) -> None:
237241 console .print (f"\n [bold]{ program .name } [/bold] ({ program .university } )" )
238242 console .print (f" Match: [{ color } ]{ match .match_score :.0%} [/{ color } ]" )
239243
244+ lr_pred = predict_prob_full (program .id , profile .gpa , gre_quant , profile )
245+ if lr_pred is not None :
246+ pcolor = "green" if lr_pred .prob >= 0.6 else "yellow" if lr_pred .prob >= 0.35 else "red"
247+ ci_str = (
248+ f" [dim][{ lr_pred .prob_low :.0%} –{ lr_pred .prob_high :.0%} ][/dim]"
249+ if lr_pred .prob_low is not None and lr_pred .prob_high is not None
250+ else ""
251+ )
252+ bc_flag = " [dim](bias-corrected)[/dim]" if lr_pred .is_bias_corrected else ""
253+ console .print (f" P(Admit): [{ pcolor } ]{ lr_pred .prob :.0%} [/{ pcolor } ]{ ci_str } { bc_flag } " )
254+
240255 if match .missing :
241256 console .print (f" [red]Missing:[/red] { ', ' .join (match .missing )} " )
242257 if match .warnings :
@@ -617,6 +632,18 @@ def cmd_interview(args: argparse.Namespace) -> None:
617632 console .print ()
618633
619634
635+ def _fmt_prob (e : Any ) -> str :
636+ """Format admission_prob + CI for display, using pre-computed SchoolListEntry fields."""
637+ prob = getattr (e , "admission_prob" , None )
638+ if prob is None :
639+ return "[dim]N/A[/dim]"
640+ pcolor = "green" if prob >= 0.6 else "yellow" if prob >= 0.35 else "red"
641+ low = getattr (e , "prob_low" , None )
642+ high = getattr (e , "prob_high" , None )
643+ ci = f" [dim][{ low :.0%} –{ high :.0%} ][/dim]" if low is not None and high is not None else ""
644+ return f"[{ pcolor } ]{ prob :.0%} [/{ pcolor } ]{ ci } "
645+
646+
620647def cmd_list (args : argparse .Namespace ) -> None :
621648 """Build and display an optimised school application list."""
622649 profile = load_profile (args .profile )
@@ -625,9 +652,12 @@ def cmd_list(args: argparse.Namespace) -> None:
625652 evaluation = evaluate_profile (profile , projected = projected )
626653 school_list = build_school_list (profile , programs , evaluation )
627654
628- # Determine GRE Quant score for LR prediction
629- gre_quant = profile .test_scores .gre_quant
630- gpa = profile .gpa
655+ # Warn if GRE is missing — LR predictions fall back to training mean
656+ if profile .test_scores .gre_quant is None :
657+ console .print (
658+ " [yellow]Note: GRE Quant not provided — P(Admit) estimates use "
659+ "program average GRE as a proxy and may be optimistic.[/yellow]"
660+ )
631661
632662 console .print ()
633663 console .print (
@@ -637,7 +667,7 @@ def cmd_list(args: argparse.Namespace) -> None:
637667 )
638668 )
639669
640- # One table per category.
670+ # One table per category — P(Admit) uses pre-computed values from rank_schools
641671 for label , entries , style in [
642672 ("Reach" , school_list .reach , "red" ),
643673 ("Target" , school_list .target , "yellow" ),
@@ -654,30 +684,16 @@ def cmd_list(args: argparse.Namespace) -> None:
654684 table .add_column ("University" , min_width = 18 )
655685 table .add_column ("Fit" , justify = "right" , width = 6 )
656686 table .add_column ("Prereq" , justify = "right" , width = 7 )
657- table .add_column ("P(Admit)" , justify = "right" , width = 9 )
687+ table .add_column ("P(Admit) [CI] " , justify = "right" , width = 20 )
658688 table .add_column ("Reason" , min_width = 28 )
659689
660690 for e in entries :
661- from core .lr_predictor import predict_prob_full
662- lr = predict_prob_full (e .program_id , gpa , gre_quant , profile )
663- if lr is not None :
664- pcolor = (
665- "green" if lr .prob >= 0.6
666- else "yellow" if lr .prob >= 0.35
667- else "red"
668- )
669- prob_str = (
670- f"[{ pcolor } ]{ lr .prob :.0%} [/{ pcolor } ]"
671- f" [dim][{ lr .prob_low :.0%} –{ lr .prob_high :.0%} ][/dim]"
672- )
673- else :
674- prob_str = "[dim]N/A[/dim]"
675691 table .add_row (
676692 e .name ,
677693 e .university ,
678694 f"{ e .fit_score :.1f} " ,
679695 f"{ e .prereq_match_score :.0%} " ,
680- prob_str ,
696+ _fmt_prob ( e ) ,
681697 e .reason ,
682698 )
683699 console .print (table )
0 commit comments