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>
This commit is contained in:
Jonathan Kirkwood
2026-07-06 14:15:12 -05:00
co-authored by Claude Fable 5
parent 1dde915540
commit b1d7aed9f4
48 changed files with 4907 additions and 971 deletions
+265
View File
@@ -0,0 +1,265 @@
"""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"