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:
co-authored by
Claude Fable 5
parent
1dde915540
commit
b1d7aed9f4
@@ -0,0 +1,116 @@
|
||||
"""Tests for ledger.py: company lifecycle, deck records, forward targets."""
|
||||
import glob
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
import ledger as ledger_mod
|
||||
|
||||
|
||||
def _record(deck_id, period, composite=70.0):
|
||||
return {"schema_version": 1, "deck_id": deck_id, "period": period,
|
||||
"composite": composite, "graded_at": "2026-07-01T00:00:00Z"}
|
||||
|
||||
|
||||
def _ft(canonical, target, target_period, direction="gte"):
|
||||
return {"name": canonical, "canonical_name": canonical, "target": target,
|
||||
"unit": "", "target_period": target_period, "direction": direction,
|
||||
"profitability": False, "source": "slide 9"}
|
||||
|
||||
|
||||
class TestLedger(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self._tmp = tempfile.TemporaryDirectory()
|
||||
self.ledger = ledger_mod.Ledger(os.path.join(self._tmp.name, "ledger"))
|
||||
|
||||
def tearDown(self):
|
||||
self._tmp.cleanup()
|
||||
|
||||
def test_ensure_company_auto_created(self):
|
||||
c = self.ledger.ensure_company("acme")
|
||||
self.assertTrue(c["auto_created"])
|
||||
self.assertEqual(c["name"], "acme")
|
||||
c2 = self.ledger.ensure_company("acme", name="Acme Robotics")
|
||||
self.assertEqual(c2["name"], "acme") # existing entry wins
|
||||
named = self.ledger.ensure_company("beta", name="Beta Corp")
|
||||
self.assertFalse(named["auto_created"])
|
||||
self.assertEqual(named["name"], "Beta Corp")
|
||||
self.assertEqual(self.ledger.all_slugs(), ["acme", "beta"])
|
||||
self.assertEqual(len(self.ledger.all_companies()), 2)
|
||||
|
||||
def test_merge_config_companies(self):
|
||||
self.ledger.ensure_company("acme")
|
||||
self.ledger.merge_config_companies([{
|
||||
"slug": "acme", "name": "Acme Robotics",
|
||||
"kpiAliases": "arr=annual recurring revenue;run_rate_arr\nchurn_rate=logo_churn",
|
||||
"pinnedTargets": [{"kpi": "cash_balance", "target": 12.0, "unit": "$M",
|
||||
"direction": "gte", "profitability": True}],
|
||||
}])
|
||||
c = self.ledger.get_company("acme")
|
||||
self.assertFalse(c["auto_created"])
|
||||
self.assertEqual(c["name"], "Acme Robotics")
|
||||
self.assertEqual(c["kpi_aliases"],
|
||||
{"arr": ["annual recurring revenue", "run_rate_arr"],
|
||||
"churn_rate": ["logo_churn"]})
|
||||
self.assertEqual(c["pinned_targets"][0]["kpi"], "cash_balance")
|
||||
# slug derived from name when absent
|
||||
self.ledger.merge_config_companies([{"name": "Beta Corp", "kpiAliases": "",
|
||||
"pinnedTargets": []}])
|
||||
self.assertIsNotNone(self.ledger.get_company("beta-corp"))
|
||||
|
||||
def test_record_supersede_prior_targets_roundtrip(self):
|
||||
path = self.ledger.record_deck("acme", _record("2026-Q1", "2026-Q1", 82.7),
|
||||
[_ft("arr", 12.0, "2026-Q2"),
|
||||
_ft("arr", 15.0, "2026-Q3")])
|
||||
self.assertTrue(os.path.isfile(path))
|
||||
self.assertEqual(
|
||||
[t["target"] for t in self.ledger.prior_targets("acme", "2026-Q2")], [12.0])
|
||||
self.assertEqual(self.ledger.prior_targets("acme", "2026-Q4"), [])
|
||||
self.assertEqual(self.ledger.prior_targets("nobody", "2026-Q2"), [])
|
||||
|
||||
# Re-grade the same deck: old record superseded (renamed), one live record.
|
||||
self.ledger.record_deck("acme", _record("2026-Q1", "2026-Q1", 80.0),
|
||||
[_ft("arr", 12.5, "2026-Q2")])
|
||||
ddir = os.path.dirname(path)
|
||||
self.assertEqual(len(glob.glob(os.path.join(ddir, "*.superseded-*.json"))), 1)
|
||||
live = self.ledger.deck_records("acme")
|
||||
self.assertEqual(len(live), 1)
|
||||
self.assertEqual(live[0]["composite"], 80.0)
|
||||
self.assertEqual(
|
||||
[t["target"] for t in self.ledger.prior_targets("acme", "2026-Q2")], [12.5])
|
||||
# history keeps one entry per period
|
||||
c = self.ledger.get_company("acme")
|
||||
self.assertEqual([h["period"] for h in c["history"]], ["2026-Q1"])
|
||||
self.assertEqual(c["history"][0]["composite"], 80.0)
|
||||
|
||||
def test_newer_deck_replaces_targets_older_does_not(self):
|
||||
self.ledger.record_deck("acme", _record("2026-Q1", "2026-Q1"),
|
||||
[_ft("arr", 15.0, "2026-Q3")])
|
||||
self.ledger.record_deck("acme", _record("2026-Q2", "2026-Q2"),
|
||||
[_ft("arr", 16.0, "2026-Q3"),
|
||||
_ft("churn_rate", 3.0, "2026-Q3", "lte")])
|
||||
targets = self.ledger.prior_targets("acme", "2026-Q3")
|
||||
self.assertEqual(sorted(t["target"] for t in targets), [3.0, 16.0])
|
||||
c = self.ledger.get_company("acme")
|
||||
self.assertEqual(c["extracted_targets"]["2026-Q3"]["from_deck"], "2026-Q2")
|
||||
# Re-recording the OLDER deck must not clobber the newer deck's targets.
|
||||
self.ledger.record_deck("acme", _record("2026-Q1", "2026-Q1"),
|
||||
[_ft("arr", 15.0, "2026-Q3")])
|
||||
targets = self.ledger.prior_targets("acme", "2026-Q3")
|
||||
self.assertEqual(sorted(t["target"] for t in targets), [3.0, 16.0])
|
||||
# History is sorted oldest first.
|
||||
c = self.ledger.get_company("acme")
|
||||
self.assertEqual([h["period"] for h in c["history"]], ["2026-Q1", "2026-Q2"])
|
||||
|
||||
def test_deck_record_lookup(self):
|
||||
self.ledger.record_deck("acme", _record("2026-Q1", "2026-Q1"), [])
|
||||
self.assertEqual(self.ledger.deck_record("acme", "2026-Q1")["period"], "2026-Q1")
|
||||
self.assertIsNone(self.ledger.deck_record("acme", "2026-Q9"))
|
||||
self.assertEqual(self.ledger.deck_records("nobody"), [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user