"""Build coach evidence blocks and SERVER_PICKS from server math. Formats precomputed probabilities for prompts; never invents numbers. """ from __future__ import annotations from typing import Any from app.stats_math import ( FORMULAS, by_emotion, by_remedy, by_tag, daily_rates, data_thin, scored_entries, server_picks, ) def strip_sensitive(text: str) -> str: """Best-effort strip of emails and long digit runs from prompt text.""" import re cleaned = re.sub( r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b", "[email]", text, ) cleaned = re.sub(r"\b\d{8,}\b", "[digits]", cleaned) return cleaned def format_evidence_block( entries: list[dict[str, Any]], daily_rows: list[dict[str, Any]], *, min_n: int, shrink_k: float, ) -> str: """Render the EVIDENCE markdown block for coach prompts.""" scored = scored_entries(entries) remedies = by_remedy(entries, min_n=min_n, shrink_k=shrink_k) tags = by_tag(entries)[:8] emotions = by_emotion(entries)[:8] rates = daily_rates(daily_rows) lines = [ "EVIDENCE (server-computed; do not invent numbers)", f"n_scored: {len(scored)}", f"min_n: {min_n}", "TOP_REMEDIES: remedy | n | p_worked | p_helped | rank", ] if remedies: for row in remedies[:10]: lines.append( f"- {row['key']} | {row['n']} | {row['p_worked']:.3f} | " f"{row['p_helped']:.3f} | {row['rank']:.3f}" ) else: lines.append("- (none above min_n)") lines.append("WORST_TAGS: tag | n | p_fail") if tags: for row in tags: lines.append(f"- {row['key']} | {row['n']} | {row['p_failed']:.3f}") else: lines.append("- (none)") lines.append("EMOTION_HITS: emotion | n | p_helped") if emotions: for row in emotions: lines.append(f"- {row['key']} | {row['n']} | {row['p_helped']:.3f}") else: lines.append("- (none)") lines.append( "DAILY_RATES: " f"p_brick_done={rates['p_brick_done']:.3f} " f"p_corn_ok={rates['p_corn_ok']:.3f} " f"p_no_fc={rates['p_no_fc']:.3f} " f"p_rerun_clean={rates['p_rerun_clean']:.3f} " f"p_court_closed={rates['p_court_closed']:.3f} " f"avg_points={rates['avg_points']:.3f}" ) lines.append( "FORMULAS: " f"p_helped={FORMULAS['p_helped']}; rank={FORMULAS['rank']}" ) lines.append(f"DATA_THIN: {str(data_thin(len(scored))).lower()}") return "\n".join(lines) def format_server_picks(picks: list[dict[str, Any]]) -> str: """Render numbered SERVER_PICKS lines for prompts and debug paste.""" if not picks: return "SERVER_PICKS: (none)" lines = ["SERVER_PICKS:"] for index, pick in enumerate(picks, start=1): lines.append( f"{index}) {pick['remedy_key']} pick={pick['pick']:.3f} " f"n={pick['n']} p_helped={pick['p_helped']:.3f}" ) return "\n".join(lines) def build_evidence( entries: list[dict[str, Any]], daily_rows: list[dict[str, Any]], current_tags: list[str], *, min_n: int, shrink_k: float, match_alpha: float, ) -> dict[str, Any]: """Return structured evidence plus formatted blocks and picks.""" scored = scored_entries(entries) picks = server_picks( entries, current_tags, min_n=min_n, shrink_k=shrink_k, match_alpha=match_alpha, ) block = format_evidence_block( entries, daily_rows, min_n=min_n, shrink_k=shrink_k, ) picks_text = format_server_picks(picks) return { "n_scored": len(scored), "min_n": min_n, "DATA_THIN": data_thin(len(scored)), "by_remedy": by_remedy(entries, min_n=min_n, shrink_k=shrink_k), "by_tag": by_tag(entries), "by_emotion": by_emotion(entries), "daily": daily_rates(daily_rows), "server_picks": picks, "evidence_block": block, "server_picks_text": picks_text, "formulas": FORMULAS, }