mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-29 15:18:24 -04:00
9794b13ed2
docs/family-manifest.md is the document the whole Phase-25/26 structural-family endgame was planned
from. Its matched-set oracle asked ov_SC01_077 ALONE: matched := {h_exact of that one overlay's
non-stub fns} | dedup hashes. So a function ABSENT from that overlay — or stubbed there but matched
in the other 133 — came out "unmatched" and was ranked as live work.
advertised real (derived)
multi-member families 2,758 -> 1,495
"hidden leverage" 11.0 MB -> 3.9 MB
matched-free lever 235/5.9 MB -> 57/1.0 MB
7.1 MB of the advertised leverage was DEAD WORK. And because `instances` counted every overlay
carrying a function — including the ones where it was already banked — the byte-weight RANKING (the
file's entire purpose: "draft these first") was sorted mostly on already-finished code, with the
real targets buried underneath. The A2 audit predicted "true frontier: 1,475 families / 3.9 MB";
derived independently here it is 1,495 / 3.9 MB.
R33: the invariant answers this with no oracle at all —
an h_exact class is WORK iff at least ONE of its instances is still an INCLUDE_ASM stub.
That also makes the dedup-hash union redundant (a dedup-shared member is by definition not a stub),
so the `hash:` regex over config/dedup.us.yaml is DELETED. `instances` now counts only the members
still to bank, so the leverage is the real x-N.
family_hseq: stub scan -> corpus (+100 curated-name stubs the func_-only regex could not see; they
had made 3 still-stubbed functions look like MATCHED exemplars, which every sweep then re-nominates,
produces nothing from, and books as a silent skip). Its hardcoded "expect ~663/~186/~1.85M" self-check
was a stale 2026-07-11 snapshot — 38 banking commits have landed since — and is now labelled a
point-in-time reference, not an invariant. (Verified my change can only GROW the frontier: +100 stubs.)
census_conflict_callees: scoped to src/<ov>/<ov>.c alone, so it saw 13 of 264 stubs and reported
"wave scope: 2 still-stub" when the truth is 57 — every downstream percentage computed against a
denominator 96% too small. Now 0/57 (the audit's exact figure). Its 0-conflict answer was right BY
LUCK; it is now right for a reason. MARKED FOR DELETION (R33): it re-derives from C text what
reconcile_tu.py answers from the build, and its parse holes fail in the UNSAFE direction (an unknown
callee is silently bucketed "conflict-free"). Delete once reconcile_tu is wired into its only consumer.
R14 near-miss, recorded: my first census patch handed collect_stubs() a set of NAMES where it wanted
ADDRESSES, so the membership test was always false and it printed 0/0. Caught only because 0
contradicted the audit's expected 57. A scanner that returns 0 is indistinguishable from a scanner
that found nothing — which is the entire thesis of this audit, and it very nearly bit me while
fixing it.
159 lines
8.5 KiB
Python
159 lines
8.5 KiB
Python
#!/usr/bin/env python3
|
||
"""Phase-25 T2: the ranked STRUCTURAL-FAMILY target manifest for the idiom-curriculum endgame.
|
||
|
||
Regroups the UNMATCHED frontier by structure (h_norm) instead of bytes (h_exact) — the Phase-24 reframe —
|
||
and emits, per family, the ONE exemplar to draft (its ov_SC01_077 member where present: the canonical harvest
|
||
overlay with cached Ghidra-C) + the family's leverage. An h_norm family is RELOC-ONLY by construction
|
||
(sig_image.norm_stream masks only jal/HI16/LO16, keeping registers+true immediates), so its members differ
|
||
ONLY in per-overlay symbol addresses; whether ONE C body matches all members is confirmed per-family by the
|
||
whole-binary byte-gate (T3 proves the magnitude; T7 banks each). Leverage = the family's INSTANCE count (how
|
||
many overlays carry it), NOT h_exact-reach (which is ~1-3 for a byte-shattered family).
|
||
|
||
.venv/bin/python tools/family_manifest.py
|
||
-> .run/family_manifest.json (full, ranked by byte-weight) + docs/family-manifest.md (digest, committed)
|
||
|
||
Ground truth = the sigs (they sign the ORIGINAL bytes, stable across matching); reproducible via
|
||
`make sig-overlays`. Companion to the frontier surveys .run/{analyze_frontier,probe_hnorm}.py.
|
||
"""
|
||
import json, glob, os, re, sys, collections
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
import corpus # the derived corpus oracle (Phase 26-A)
|
||
|
||
sig_by_ov = {}
|
||
for p in sorted(glob.glob(".run/sig.ov_*.jsonl")):
|
||
ov = p.split("sig.")[1][:-6]
|
||
recs = {}
|
||
for line in open(p):
|
||
line = line.strip()
|
||
if not line:
|
||
continue
|
||
d = json.loads(line)
|
||
recs[int(d["addr"], 16)] = (d["nins"], d["h_exact"], d["h_norm"])
|
||
sig_by_ov[ov] = recs
|
||
|
||
# ---- THE MATCHED SET, DERIVED (Phase 26-A audit, HIGH — R33) --------------------------------------
|
||
# The old oracle asked ov_SC01_077 ALONE: matched := {h_exact of its non-stub fns} | dedup hashes.
|
||
# That is the wrong question. A function absent from that one overlay — or stubbed there but matched
|
||
# in the 133 others — came out "unmatched", so it was ranked as live work.
|
||
#
|
||
# MEASURED CONSEQUENCE: docs/family-manifest.md, the document the whole Phase-25/26 endgame is planned
|
||
# from, advertised "2,758 multi-member families / 11.0 MB of hidden leverage". 1,071 of them (6.80 MB,
|
||
# **62% of the advertised byte-weight**) were ALREADY FULLY MATCHED — pure phantom targets. A further
|
||
# 253 had their byte-weight inflated by already-matched members. The byte-weight RANKING — the entire
|
||
# purpose of the file, "draft these first" — was therefore sorted mostly on dead work, with the real
|
||
# targets buried underneath.
|
||
#
|
||
# The invariant answers it exactly, per overlay, with no oracle at all:
|
||
# an h_exact class is WORK iff at least ONE of its instances is still an INCLUDE_ASM stub somewhere.
|
||
# (And the dedup-hash union is now redundant: a dedup-shared member is by definition not a stub. One
|
||
# more scanner deleted — the `hash:` regex over config/dedup.us.yaml is gone.)
|
||
stub_by_ov = {ov: set(corpus.stubs(ov)) for ov in sig_by_ov}
|
||
sig077 = sig_by_ov.get("ov_SC01_077", {})
|
||
stub077 = stub_by_ov.get("ov_SC01_077", set())
|
||
|
||
# per h_exact class: which overlays carry it, and in which is it STILL A STUB
|
||
hexcls = {}
|
||
for ov, recs in sig_by_ov.items():
|
||
st = stub_by_ov[ov]
|
||
for v, (n, hx, hn) in recs.items():
|
||
e = hexcls.setdefault(hx, {"ovs": set(), "stub_ovs": set(), "n": n, "rep": v, "hn": hn})
|
||
e["ovs"].add(ov)
|
||
if v in st:
|
||
e["stub_ovs"].add(ov)
|
||
if ov == "ov_SC01_077":
|
||
e["rep"] = v
|
||
|
||
# UNMATCHED h_exact classes -> group by h_norm (the structural family)
|
||
fam = collections.defaultdict(lambda: {"hexclasses": 0, "instances": 0, "nins": 0, "bw": 0, "rep": 0, "maxhexreach": 0})
|
||
for hx, e in hexcls.items():
|
||
if not e["stub_ovs"]:
|
||
continue # fully matched fleet-wide -> NOT work (was: counted as work)
|
||
n, hn, v = e["n"], e["hn"], e["rep"]
|
||
r = len(e["stub_ovs"]) # the REAL x-N leverage: only the members still to bank
|
||
f = fam[hn]
|
||
f["hexclasses"] += 1
|
||
f["instances"] += r
|
||
f["bw"] += r * n * 4
|
||
f["maxhexreach"] = max(f["maxhexreach"], len(e["ovs"]))
|
||
if n >= f["nins"] or f["rep"] == 0:
|
||
f["rep"] = v
|
||
f["nins"] = n
|
||
|
||
# the draftable exemplar per family: the largest UNMATCHED ov_SC01_077 stub whose h_norm == the family
|
||
ov077_ex = {} # h_norm -> (vram, nins)
|
||
for v, (n, hx, hn) in sig077.items():
|
||
if v not in stub077:
|
||
continue
|
||
if hn not in ov077_ex or n > ov077_ex[hn][1]:
|
||
ov077_ex[hn] = (v, n)
|
||
|
||
|
||
def bucket(n):
|
||
return "tiny" if n < 20 else "small" if n < 50 else "med" if n < 100 else "large" if n < 150 else "GIANT"
|
||
|
||
|
||
rows = []
|
||
for hn, f in fam.items():
|
||
ex = ov077_ex.get(hn)
|
||
rows.append({
|
||
"hnorm": hn,
|
||
"rep_addr": f"0x{f['rep']:08x}",
|
||
"ov077_exemplar": (f"0x{ex[0]:08x}" if ex else None),
|
||
"n_hexcls": f["hexclasses"],
|
||
"instances": f["instances"],
|
||
"max_nins": f["nins"],
|
||
"max_hex_reach": f["maxhexreach"],
|
||
"byte_weight": f["bw"],
|
||
"size_bucket": bucket(f["nins"]),
|
||
"multi_member": f["hexclasses"] >= 2,
|
||
})
|
||
rows.sort(key=lambda r: -r["byte_weight"])
|
||
json.dump(rows, open(".run/family_manifest.json", "w"), indent=0)
|
||
|
||
multi = [r for r in rows if r["multi_member"]]
|
||
with_ex = [r for r in multi if r["ov077_exemplar"]]
|
||
|
||
# classify the multi-member families by ov_SC01_077 membership -> the endgame's 3 levers
|
||
ov077_matched_hn = {hn for v, (n, hx, hn) in sig077.items() if v not in stub077}
|
||
lev = {"draftable": [0, 0], "matched_free": [0, 0], "absent": [0, 0]}
|
||
for r in multi:
|
||
k = "draftable" if r["ov077_exemplar"] else ("matched_free" if r["hnorm"] in ov077_matched_hn else "absent")
|
||
lev[k][0] += 1
|
||
lev[k][1] += r["byte_weight"]
|
||
|
||
L = ["# Phase 25 — Structural-family target manifest (T2)\n"]
|
||
L.append("> Generated by `tools/family_manifest.py` from the 134 overlay sigs + ov_SC01_077 matched set + "
|
||
"`config/dedup.us.yaml`. One exemplar per h_norm family, drafted from its **ov_SC01_077 member** where "
|
||
"present. h_norm families are reloc-only by construction; whether one C body matches all members is "
|
||
"confirmed per-family by the byte-gate (T3 magnitude / T7 banks). **Leverage = `inst` (fleet-wide member "
|
||
"count), NOT `hexR` (h_exact-reach, ~1-3 for byte-shattered families).**\n")
|
||
L.append(f"**Families:** {len(rows)} · **multi-member (hidden leverage):** {len(multi)} / "
|
||
f"{sum(r['byte_weight'] for r in multi)/1e6:.1f} MB · **with an ov_SC01_077 draftable exemplar:** {len(with_ex)}.\n")
|
||
L.append(f"**Endgame levers** (multi-member families × ov_SC01_077 membership): **draftable** {lev['draftable'][0]} / "
|
||
f"{lev['draftable'][1]/1e6:.1f} MB (unmatched ov077 member → draft the exemplar, T5/T7) · **matched-free** "
|
||
f"{lev['matched_free'][0]} / {lev['matched_free'][1]/1e6:.1f} MB (matched ov077 member + unmatched siblings → "
|
||
f"free `--tier h_norm` propagation, T3) · **absent** {lev['absent'][0]} / {lev['absent'][1]/1e6:.1f} MB "
|
||
f"(no ov077 member → draft from another overlay).\n")
|
||
L.append("| # | rep addr | ov077 exemplar | nins | hexcls | inst | hexR | byteMB | bucket |")
|
||
L.append("|--:|----------|----------------|-----:|-------:|-----:|-----:|-------:|--------|")
|
||
for i, r in enumerate(multi[:60], 1):
|
||
L.append(f"| {i} | {r['rep_addr']} | {r['ov077_exemplar'] or '—'} | {r['max_nins']} | {r['n_hexcls']} | "
|
||
f"{r['instances']} | {r['max_hex_reach']} | {r['byte_weight']/1e6:.2f} | {r['size_bucket']} |")
|
||
open("docs/family-manifest.md", "w").write("\n".join(L) + "\n")
|
||
|
||
print(f"families {len(rows)} | multi-member {len(multi)} ({sum(r['byte_weight'] for r in multi)/1e6:.1f} MB) | "
|
||
f"ov077-draftable {len(with_ex)}")
|
||
print(f"levers: draftable {lev['draftable'][0]}/{lev['draftable'][1]/1e6:.1f}MB | "
|
||
f"matched-free {lev['matched_free'][0]}/{lev['matched_free'][1]/1e6:.1f}MB | "
|
||
f"absent {lev['absent'][0]}/{lev['absent'][1]/1e6:.1f}MB")
|
||
print("-> .run/family_manifest.json + docs/family-manifest.md")
|
||
|
||
# T3-ready picks: mid-size (100-150 ins) multi-member family, ov077-draftable, spanning most overlays
|
||
t3 = [r for r in multi if r["ov077_exemplar"] and 100 <= r["max_nins"] <= 150 and r["instances"] >= 100]
|
||
t3.sort(key=lambda r: (-r["instances"], -r["byte_weight"]))
|
||
print("\nT3 swing-question candidates (mid-size 100-150 ins, ov077-draftable, inst>=100):")
|
||
for r in t3[:10]:
|
||
print(f" ex={r['ov077_exemplar']} nins={r['max_nins']} inst={r['instances']} hexcls={r['n_hexcls']} "
|
||
f"bw={r['byte_weight']/1e6:.2f}MB")
|