Files
boardroom-map/orchestrator/scorecard.py
T
Jonathan KirkwoodandClaude Fable 5 b1d7aed9f4 Implement BDEF v1.1 grading: scoring core, per-deck pipeline, ledger, dashboard, StartOS layer
- Deterministic scoring.py (quant 60 / qual 40 / flags -15, profitability heaviest)
- Per-company JSON ledger with forecast-target chaining deck N-1 -> N
- Single-shot sandbox agent with guided-JSON fallback ladder (no tool loop)
- Portfolio dashboard with sparklines, KPI hit rates, BDEF category bars
- 48 unit tests green; endpoints smoke-tested; npm check+build green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 14:15:12 -05:00

266 lines
10 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Markdown renderers: per-deck DECK_REPORT and per-company SCORECARD.
Pure string builders over the scoring record shape (scoring.score_deck) and
ledger deck records — no I/O here; jobs.py decides where the files land.
"""
from __future__ import annotations
_CATEGORIES = "ABCDEFGH"
_CATEGORY_TITLES = {
"A": "Incentive Alignment & Skin in the Game",
"B": "Inversion Discipline & Margin of Safety",
"C": "Circle of Competence & Rational Learning",
"D": "Capital Allocation Quality",
"E": "Moat Durability & Competitive Reality",
"F": "Psychological & Cultural Health",
"G": "Simplicity, Clarity & Decision Velocity",
"H": "Board Value-Add & Governance Quality",
}
def _fmt(x, digits: int = 1) -> str:
if x is None:
return "—"
if isinstance(x, bool):
return "yes" if x else "no"
if isinstance(x, float):
return f"{x:.{digits}f}"
return str(x)
def _num(x, unit: str = "") -> str:
if x is None:
return "—"
s = f"{x:g}" if isinstance(x, (int, float)) else str(x)
return f"{s}{unit}" if unit and unit in ("%",) else (f"{s} {unit}".strip() if unit else s)
def _bucket_row(name: str, b: dict) -> str:
if b.get("na"):
return f"| {name} | — | — | {b.get('kpi_count', 0)} | NA — weight redistributed |"
return (f"| {name} | {_fmt(b.get('weight'))} | {_fmt(b.get('score'))} "
f"| {b.get('kpi_count', 0)} | |")
def render_deck_report(record: dict, extraction: dict, adjudication_md: str | None = None) -> str:
"""One deck's full markdown report."""
lines: list[str] = []
company = record.get("company") or "?"
period = record.get("period") or "unknown period"
lines.append(f"# Deck report — {company} · {period}")
lines.append("")
lines.append(f"## Composite: **{_fmt(record.get('composite'))} / 100**")
lines.append("")
q = record.get("quant", {})
lines.append(f"Quant {_fmt(q.get('score'))} · Qual {_fmt(record.get('qual', {}).get('score'))}"
f" · Penalties {_fmt(record.get('penalties', {}).get('total'))}"
f" · graded {record.get('graded_at') or '?'} (job {record.get('job_id') or '?'})")
lines.append("")
# --- quantitative buckets
lines.append("## Quantitative (max 60)")
lines.append("")
lines.append("| Bucket | Weight | Score | KPIs | Note |")
lines.append("|---|---|---|---|---|")
lines.append(_bucket_row("Profitability KPIs", q.get("profitability", {})))
lines.append(_bucket_row("Other KPIs", q.get("other", {})))
lines.append(_bucket_row("Forecast integrity", q.get("forecast_integrity", {})))
lines.append("")
kpi_results = record.get("kpi_results") or []
if kpi_results:
lines.append("### KPI results")
lines.append("")
lines.append("| KPI | Actual | Target | Source | Credit |")
lines.append("|---|---|---|---|---|")
for r in kpi_results:
name = r.get("name") or r.get("canonical_name") or "?"
if r.get("matched_via") == "fuzzy":
name += " (≈ matched via fuzzy)"
src = r.get("target_source") or "—"
credit = "—" if r.get("credit") is None else _fmt(r.get("credit"), 2)
lines.append(f"| {name} | {_num(r.get('actual'), r.get('unit') or '')} "
f"| {_num(r.get('target'), r.get('unit') or '')} | {src} | {credit} |")
lines.append("")
fresults = record.get("forecast_results") or []
if fresults:
lines.append("### Forecast integrity (prior targets vs this period's actuals)")
lines.append("")
lines.append("| KPI | Prior target | Actual | Accuracy |")
lines.append("|---|---|---|---|")
for r in fresults:
lines.append(f"| {r.get('canonical_name')} | {_num(r.get('target'))} "
f"| {_num(r.get('actual'))} | {_fmt(r.get('accuracy'), 2)} |")
lines.append("")
# --- qualitative
lines.append("## Qualitative (max 40)")
lines.append("")
lines.append("| Category | Median | Evidence quality | Adjusted | Points |")
lines.append("|---|---|---|---|---|")
cats = record.get("qual", {}).get("categories", {})
for cid in _CATEGORIES:
c = cats.get(cid, {})
lines.append(f"| {cid}. {_CATEGORY_TITLES[cid]} | {_fmt(c.get('median'))} "
f"| {_fmt(c.get('evidence_quality'), 2)} | {_fmt(c.get('adjusted'), 2)} "
f"| {_fmt(c.get('points'), 2)} |")
lines.append("")
for cid in _CATEGORIES:
c = cats.get(cid, {})
rats = c.get("rationales") or []
if not rats:
continue
best = max(rats, key=lambda r: sum(len(e.get("quote") or "") for e in r.get("evidence") or []))
lines.append(f"### {cid}. {_CATEGORY_TITLES[cid]}")
lines.append("")
lines.append(f"**{best.get('grader')}**: {best.get('rationale')}")
for ev in best.get("evidence") or []:
loc = f" — {ev.get('location')}" if ev.get("location") else ""
lines.append(f"> \"{ev.get('quote')}\"{loc}")
lines.append("")
# --- red flags
flags = record.get("penalties", {}).get("flags") or []
lines.append(f"## Red flags (penalty {_fmt(record.get('penalties', {}).get('total'))})")
lines.append("")
if flags:
lines.append("| Code | Severity | Points | Sources | Description |")
lines.append("|---|---|---|---|---|")
for f in flags:
lines.append(f"| `{f.get('code')}` | {f.get('severity')} | {_fmt(f.get('points'))} "
f"| {', '.join(f.get('sources') or [])} | {f.get('description')} |")
else:
lines.append("None raised.")
lines.append("")
# --- narrative
narrative = record.get("narrative") or extraction.get("narrative") or {}
if narrative.get("summary"):
lines.append("## Narrative")
lines.append("")
lines.append(narrative["summary"])
lines.append("")
asks = narrative.get("asks") or []
if asks:
lines.append("### Asks")
lines.append("")
for a in asks:
lines.append(f"- {a}")
lines.append("")
if adjudication_md:
lines.append("## Panel adjudication")
lines.append("")
lines.append(adjudication_md.strip())
lines.append("")
return "\n".join(lines).rstrip() + "\n"
def _arrow(delta: float) -> str:
if delta > 0:
return "↑"
if delta < 0:
return "↓"
return "→"
def render_scorecard(company: dict, records: list[dict]) -> str:
"""Company SCORECARD.md across all live deck records (oldest first)."""
name = company.get("name") or company.get("slug") or "?"
lines: list[str] = [f"# Scorecard — {name}", ""]
if not records:
lines.append("No graded decks yet.")
return "\n".join(lines) + "\n"
latest = records[-1]
prev = records[-2] if len(records) > 1 else None
comp = latest.get("composite") or 0.0
if prev is not None:
delta = round(comp - (prev.get("composite") or 0.0), 1)
lines.append(f"## Latest composite: **{_fmt(comp)}** ({latest.get('period')}) "
f"{_arrow(delta)} {'+' if delta > 0 else ''}{_fmt(delta)} vs {prev.get('period')}")
else:
lines.append(f"## Latest composite: **{_fmt(comp)}** ({latest.get('period')}) — first graded deck")
lines.append("")
# --- composite history
lines.append("## Composite history")
lines.append("")
lines.append("| Period | Composite | Quant | Qual | Penalties |")
lines.append("|---|---|---|---|---|")
for r in records:
lines.append(f"| {r.get('period') or '?'} | {_fmt(r.get('composite'))} "
f"| {_fmt(r.get('quant', {}).get('score'))} "
f"| {_fmt(r.get('qual', {}).get('score'))} "
f"| {_fmt(r.get('penalties', {}).get('total'))} |")
lines.append("")
# --- categories latest vs previous
lines.append("## BDEF categories (latest vs previous)")
lines.append("")
lines.append("| Category | Latest | Previous | Δ |")
lines.append("|---|---|---|---|")
lcats = latest.get("qual", {}).get("categories", {})
pcats = (prev or {}).get("qual", {}).get("categories", {})
for cid in _CATEGORIES:
lp = lcats.get(cid, {}).get("points")
pp = pcats.get(cid, {}).get("points")
if lp is not None and pp is not None:
d = round(lp - pp, 2)
dcol = f"{_arrow(d)} {'+' if d > 0 else ''}{_fmt(d, 2)}"
else:
dcol = "—"
lines.append(f"| {cid}. {_CATEGORY_TITLES[cid]} | {_fmt(lp, 2)} | {_fmt(pp, 2)} | {dcol} |")
lines.append("")
# --- KPI hit-rate across records
order: list[str] = []
per_kpi: dict[str, list] = {}
for r in records:
for k in r.get("kpi_results") or []:
cn = k.get("canonical_name") or k.get("name") or "?"
if cn not in per_kpi:
per_kpi[cn] = []
order.append(cn)
per_kpi[cn].append(k.get("credit"))
lines.append("## KPI hit-rate")
lines.append("")
lines.append("| KPI | Attempts | Hits | Streak | Last credit |")
lines.append("|---|---|---|---|---|")
for cn in order:
credits = [c for c in per_kpi[cn] if c is not None]
if not credits:
continue
hits = sum(1 for c in credits if c >= 1)
streak = 0
for c in reversed(credits):
if c >= 1:
streak += 1
else:
break
lines.append(f"| {cn} | {len(credits)} | {hits} | {streak} | {_fmt(credits[-1], 2)} |")
lines.append("")
# --- open flags on the latest deck
flags = latest.get("penalties", {}).get("flags") or []
lines.append(f"## Open flags ({latest.get('period')})")
lines.append("")
if flags:
lines.append("| Code | Severity | Points | Sources | Description |")
lines.append("|---|---|---|---|---|")
for f in flags:
lines.append(f"| `{f.get('code')}` | {f.get('severity')} | {_fmt(f.get('points'))} "
f"| {', '.join(f.get('sources') or [])} | {f.get('description')} |")
else:
lines.append("None.")
lines.append("")
# --- deck reports
lines.append("## Deck reports")
lines.append("")
for r in records:
lines.append(f"- {r.get('period') or '?'} — composite {_fmt(r.get('composite'))} — "
f"decks/{r.get('deck_id')}.json / DECK_REPORT.md")
return "\n".join(lines).rstrip() + "\n"