mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-29 15:18:24 -04:00
a5bad7f48d
tools/burndown.py snapshots the 3 fleet metrics + remaining substantial frontier each run (docs/burndown.jsonl, git-HEAD-keyed), computes velocity vs the previous commit-snapshot, and flags the yield floor (mean instr-pp over last 3 snapshots < threshold => 'consider closing P29'). Seeded with the session-4-close baseline. Reads progress.fleet.md + family-hseq.md (regen those first for a true reading).
135 lines
6.2 KiB
Python
135 lines
6.2 KiB
Python
#!/usr/bin/env python3
|
|
"""burndown.py — Phase-29 Task-7/11: the burn-down + velocity tracker (the ROI-close instrument).
|
|
|
|
The Phase-29 milestone is NOT a checkbox count — it is "close when per-session yield floors out"
|
|
(the ROI-gated close Drew scoped at phase start). This tool makes that floor VISIBLE: each run it
|
|
snapshots the fleet's 3 headline metrics + the remaining substantial crack-frontier, appends the
|
|
snapshot to .run/burndown.jsonl, computes velocity vs the previous snapshot, and flags when recent
|
|
yield has dropped below the floor threshold.
|
|
|
|
INPUTS (read the CURRENT committed digests — regenerate them first for a fresh reading):
|
|
- docs/progress.fleet.md (via `make report` / `make tools-health`) -> the 3 metrics
|
|
- docs/family-hseq.md (via `tools/family_hseq.py`) -> remaining substantial frontier
|
|
Run order for a true reading: make report && .venv/bin/python tools/family_hseq.py && tools/burndown.py
|
|
|
|
OUTPUT: a burn-down summary (current metrics, remaining frontier, velocity since last snapshot, and a
|
|
FLOOR verdict) + an appended snapshot in .run/burndown.jsonl (git HEAD keyed, so re-runs on the same
|
|
commit UPDATE rather than duplicate).
|
|
|
|
The whole-binary byte-gate remains the sole arbiter of a match (G3/P9); this only MEASURES progress.
|
|
"""
|
|
import json, os, re, sys, subprocess, argparse
|
|
|
|
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
LOG = os.path.join(REPO, "docs", "burndown.jsonl") # tracked (committed) so velocity persists across sessions
|
|
FLEET = os.path.join(REPO, "docs", "progress.fleet.md")
|
|
HSEQ = os.path.join(REPO, "docs", "family-hseq.md")
|
|
|
|
|
|
def parse_fleet():
|
|
"""(instr_pct, distinct_pct, fn_pct) from progress.fleet.md — the authoritative digest."""
|
|
txt = open(FLEET).read()
|
|
def pct(label):
|
|
m = re.search(rf"FLEET {label}[^\n]*?=\s*([0-9.]+)%", txt)
|
|
return float(m.group(1)) if m else None
|
|
return {
|
|
"instr_pct": pct(r"instr-weighted"),
|
|
"distinct_pct": pct(r"distinct-code"),
|
|
"fn_pct": pct(r"fn-count byte-ident"),
|
|
}
|
|
|
|
|
|
def parse_frontier():
|
|
"""(substantial_families, templatable_ins, matched_sib) from family-hseq.md."""
|
|
txt = open(HSEQ).read()
|
|
m = re.search(r"Substantial:\s*\*\*([\d,]+)\s*families\s*/\s*([\d,]+)\s*templatable ins\*\*,\s*(\d+)\s*with a matched sibling", txt)
|
|
if not m:
|
|
return {"substantial_families": None, "templatable_ins": None, "matched_sib": None}
|
|
return {
|
|
"substantial_families": int(m.group(1).replace(",", "")),
|
|
"templatable_ins": int(m.group(2).replace(",", "")),
|
|
"matched_sib": int(m.group(3)),
|
|
}
|
|
|
|
|
|
def git_head():
|
|
return subprocess.run(["git", "-C", REPO, "rev-parse", "--short", "HEAD"],
|
|
capture_output=True, text=True).stdout.strip() or "unknown"
|
|
|
|
|
|
def load_log():
|
|
if not os.path.exists(LOG):
|
|
return []
|
|
return [json.loads(l) for l in open(LOG) if l.strip()]
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--label", default="", help="optional session label for this snapshot")
|
|
ap.add_argument("--floor-pp", type=float, default=0.3,
|
|
help="instr-pp/snapshot below which yield is 'at the floor' (default 0.3)")
|
|
ap.add_argument("--no-append", action="store_true", help="report only; do not write the snapshot")
|
|
a = ap.parse_args()
|
|
|
|
fleet, front, head = parse_fleet(), parse_frontier(), git_head()
|
|
if fleet["instr_pct"] is None:
|
|
sys.exit("burndown: could not parse docs/progress.fleet.md — run `make report` first.")
|
|
snap = {"head": head, "label": a.label, **fleet, **front}
|
|
|
|
log = load_log()
|
|
prev = next((s for s in reversed(log) if s.get("head") != head), None) # last DIFFERENT commit
|
|
|
|
# velocity vs the previous distinct-commit snapshot
|
|
dv = {}
|
|
if prev:
|
|
for k in ("instr_pct", "distinct_pct", "fn_pct"):
|
|
if snap.get(k) is not None and prev.get(k) is not None:
|
|
dv[k] = round(snap[k] - prev[k], 2)
|
|
|
|
# append/update (dedupe on HEAD so re-runs on the same commit overwrite)
|
|
if not a.no_append:
|
|
log = [s for s in log if s.get("head") != head] + [snap]
|
|
os.makedirs(os.path.dirname(LOG), exist_ok=True)
|
|
with open(LOG, "w") as f:
|
|
for s in log:
|
|
f.write(json.dumps(s) + "\n")
|
|
|
|
# ---- report ----
|
|
print("=" * 64)
|
|
print(f"BURN-DOWN (HEAD {head}{' ' + a.label if a.label else ''})")
|
|
print("=" * 64)
|
|
print(f" instr-weighted : {fleet['instr_pct']}%"
|
|
+ (f" ({dv['instr_pct']:+.2f} pp since {prev['head']})" if "instr_pct" in dv else ""))
|
|
print(f" distinct-code : {fleet['distinct_pct']}%"
|
|
+ (f" ({dv['distinct_pct']:+.2f} pp)" if "distinct_pct" in dv else ""))
|
|
print(f" fn-count : {fleet['fn_pct']}%"
|
|
+ (f" ({dv['fn_pct']:+.2f} pp)" if "fn_pct" in dv else ""))
|
|
print("-" * 64)
|
|
if front["substantial_families"] is not None:
|
|
crackable = front["substantial_families"] - (front["matched_sib"] or 0)
|
|
print(f" REMAINING substantial frontier: {front['substantial_families']} families "
|
|
f"/ {front['templatable_ins']:,} templatable ins")
|
|
print(f" - {front['matched_sib']} matched-sibling (zero-crack sweep) + ~{crackable} needing a crack")
|
|
print("-" * 64)
|
|
|
|
# ---- floor verdict: mean instr-pp over the last N inter-commit deltas ----
|
|
hist = []
|
|
for i in range(1, len(log)):
|
|
a_, b_ = log[i - 1], log[i]
|
|
if a_.get("head") != b_.get("head") and a_.get("instr_pct") and b_.get("instr_pct"):
|
|
hist.append(round(b_["instr_pct"] - a_["instr_pct"], 2))
|
|
if len(hist) >= 3:
|
|
recent = hist[-3:]
|
|
mean = sum(recent) / len(recent)
|
|
verdict = "AT THE FLOOR — consider closing P29" if mean < a.floor_pp else "above floor — keep cracking"
|
|
print(f" velocity (last 3 snapshots, instr pp): {recent} mean {mean:+.2f}")
|
|
print(f" FLOOR VERDICT (threshold {a.floor_pp} pp): {verdict}")
|
|
else:
|
|
print(f" velocity: {len(hist)} inter-commit delta(s) logged — need >=3 for a floor verdict.")
|
|
print(f" (seed more snapshots each session: `make report && tools/family_hseq.py && tools/burndown.py`)")
|
|
print("=" * 64)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|