Files
Drew T 827295e241 tools+docs(phase-33.5): task 13.5 — the tools audit + the two dictionaries: tools/tool_census.py (two agreeing enumerations of 327 tool files; docstring/SETUP row/consumers/class derived from the tree; the authored half in config/tool_dictionary.tsv — phase · portability · the NEED each tool answers · what · adapts · verdict — with coverage asserted both ways) → docs/tool-index.md (need-keyed, KEEP-GEN, Reference-index row, wiki + how-to pointers), the kit's tools/MANIFEST.md regenerated (header states live 293 + superseded 28 = 321 rows), and the two verbatim corpora in-tree (Drew, confirmed S91): decomp-architect/corpus/tools/<phase>/ (302 copies + 28 superseded pointers + INDEX) and corpus/cookbook/ (the cookbook, its symptom index, the codegen map, a front page stating what transfers per compiler) — sha1-equal to their sources by tool_census --check in tools-health, regenerated by make kit-corpus; kit_lint exempts the corpus dirs (verbatim evidence) but syntax-checks them; G66 (consult the tool dictionary first) + G67 (translate an inherited idiom through its pass) + two memory seeds (34 at install); SETUP Step 6 installs docs/knowledge-corpus.md and checks the manifest against its own stated total; the ops-setup dictionary rows; the intake's Phase 7 cites G66/G67 and Phase 10 + Part C name the raw-cast → declared-symbol step; templates/layout-contract.md (the five-tool probe, a draft for the split). The review under Drew's criterion: 93 no-consumer tools (one Opus agent's draft, verified: 0 defects, every successor live, 0 live consumers, 0 collisions; four one-off verdicts overturned to STILL-NEEDED) → 34 retired by git mv to tools/sunset/ (28 superseded, 6 one-offs; README review table; SETUP rows moved; Archive-index group). Run 4 (fresh throwaway, the final kit): stopped on my Step-6 check (321 vs the live 293) → both sides derived → resumed → PASS 10/10, manifest 56 == 56, 4 commits, guardrails held (the one foreign path was the timeline regenerated by the detached tools-health). tools-health OK; doc_links --strict rc 0; audit_public OK over 6,842 paths; the purge probe PASSED (Phase 34's gate open). decision-log "P33.5 S91" + accelerators "P33.5 S91" banked; log + checkpoint (NEXT = task 14, xHigh, fresh session)
2026-09-07 22:09:15 -06:00

160 lines
9.1 KiB
Python
Raw Permalink 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.
#!/usr/bin/env python3
"""exemplar_miner.py — route every residual stub to its lever, rank the reach-134 work (Phase 20 T2).
Consumes the residual census (tools/wall_taxonomy.json: per-stub bucket/nins/mismatch for the canonical
source overlay ov_SC01_077) and computes each stub's FLEET REACH (how many of the 134 overlays carry a
byte-identical copy, the ×N propagation leverage) the same way dedup_propagate does (h_exact over the
per-overlay sigs). It then:
- routes each bucket to a lever (WAVE / PINS / STRUCT / STUB) — ADVISORY; the byte-gate is the sole
arbiter (G3/P9), this is a worklist, not a correctness claim,
- emits the reach-134 WAVE-target list (T6 fuel; ranked reach desc, nins asc),
- surfaces the PINS/permuter-class reach-134 near-misses (the class-crack candidate pool for T3),
- tallies the honest STUB residual (ARITY_WALL loose-typing + NONFAITHFUL) and the STRUCT-context band.
Note: wall_taxonomy's `mismatch` is the M2C-DRAFT mismatch (scaffold quality), NOT the hand-match floor —
a STRUCTURAL_MISS with a high mismatch can still hand-match to a 1-instruction residual (e.g. the loop-guard
exemplar func_8012C2D0). So the buckets size the POOLS; the cleanest class-isolating exemplar is a Max pick.
Outputs: docs/exemplar_curriculum.md (human worklist) + .run/exemplar_routing.json (machine, for the wave gen).
Usage: tools/exemplar_miner.py [--source ov_SC01_077] [--census .run/wall_taxonomy.json] [--top 60]
"""
import argparse, json, os, sys, pathlib, datetime
ROOT = pathlib.Path(__file__).resolve().parent.parent
sys.path.insert(0, str(ROOT / "tools"))
import dedup_propagate as dp # load_sig, onboarded_overlays (reach == its h_exact computation)
import corpus # the derived stub oracle (Phase 26-A) — "still work?" = "still INCLUDE_ASM"
# bucket -> lever. ADVISORY routing (the byte-gate decides truth). Grouped by how we'd actually attack it:
# WAVE = m2c/hand-draftable by the Ultracode swarm + §17 toolkit + canon-first gate + fix_arity_callers
# STRUCT = m2c can't draft until a type is known (fn-ptr tables, jump tables, struct derefs)
# PINS = regalloc/schedule near-miss -> register-pins hand-match (permuter grind skipped this phase);
# the small-mismatch reach-134 ones are the class-crack candidate pool (T3)
# STUB = fundamental (loose-typing ARITY_WALL) or non-faithful (GTE/handwritten) -> honest INCLUDE_ASM
LEVER = {
"STRUCTURAL_MISS": "WAVE", "SIG_FIXABLE_KR": "WAVE", "LEAF_READY": "WAVE",
"MCOMPILE_arg-arity": "WAVE", "MCOMPILE_undeclared-other": "WAVE", "MCOMPILE_stack-var": "WAVE",
"MCOMPILE_m2c-incomplete-arg": "WAVE", "DATA_CONFLICT": "WAVE", "OTHER_CONFLICT": "WAVE",
"MCOMPILE_other": "WAVE", "VOID_VALUE_MISUSE": "WAVE",
"MCOMPILE_fnptr-call": "STRUCT", "M2C_DECOMP_FAIL": "STRUCT", "MCOMPILE_bad-deref": "STRUCT",
"MCOMPILE_bad-switch": "STRUCT",
"PERMUTER_CLASS": "PINS",
"ARITY_WALL": "STUB", "NONFAITHFUL_DEFER": "STUB", "NO_ASM": "STUB", "M2C_EMPTY": "STUB",
}
# the named class-crack exemplars carried from Phase 18/19 (T3 targets); the m2c bucket understates them.
CLASS_EXEMPLARS = {
"8012C2D0": "loop-guard operand-order (loop.c get_condition) — T3b",
"8014F2E0": "store-vs-load scheduling tie-break (sched.c) — T3c",
"8013C360": "-O0 %lo-folding cluster (address-mode split) — T3a",
}
def main():
ap = argparse.ArgumentParser()
ap.add_argument("--source", default="ov_SC01_077")
ap.add_argument("--census", default=".run/wall_taxonomy.json")
ap.add_argument("--top", type=int, default=60)
a = ap.parse_args()
recs = json.load(open(ROOT / a.census))
pool = dp.onboarded_overlays()
sigs = {ov: dp.load_sig(ov) for ov in pool}
# "Is this census entry still work?" — answered by the INVARIANT (R33), not the dedup registry.
# registered_addrs() (config/dedup.us.yaml) is a PROXY: a function matched-but-not-registered
# (banked inline, or matched-but-local) is absent from it, so the old filter kept matched
# functions in the residual pool (the audit measured ~60% wrong). A function is unmatched iff it
# is still an INCLUDE_ASM stub in the source — which corpus.stubs derives from the tree.
live_stub_addrs = set(corpus.stubs(a.source)) # {addr_int: Stub} -> the set of addr ints
def reach(addr_int):
h = sigs[a.source].get(addr_int, {}).get("h_exact")
if not h:
return 0
return sum(1 for ov in pool if sigs[ov].get(addr_int, {}).get("h_exact") == h)
rows = []
for r in recs:
ai = int(r["addr"], 16)
if ai not in live_stub_addrs: # not a live INCLUDE_ASM stub -> already matched, not a residual
continue
lever = LEVER.get(r["bucket"], "WAVE")
rows.append({"addr": r["addr"].upper(), "nins": r["nins"], "mismatch": r.get("mismatch"),
"bucket": r["bucket"], "lever": lever, "reach": reach(ai)})
# machine output for the wave generator
os.makedirs(ROOT / ".run", exist_ok=True)
json.dump({x["addr"]: x for x in rows}, open(ROOT / ".run/exemplar_routing.json", "w"), indent=1)
# ---- human worklist ----
by_lever = {}
for x in rows:
by_lever.setdefault(x["lever"], []).append(x)
snap = datetime.datetime.fromtimestamp((ROOT / a.census).stat().st_mtime).strftime("%Y-%m-%d")
L = ["# BFM residual curriculum / router (generated by tools/exemplar_miner.py)",
f"# census: {a.census} (snapshot {snap}, {len(rows)} unregistered residual stubs in {a.source})",
"# reach = #overlays sharing the byte-identical copy (×N propagation leverage), computed from sigs.",
"# ROUTING IS ADVISORY — the per-overlay byte-gate is the sole arbiter (G3/P9). `mismatch` is the",
"# M2C-DRAFT mismatch (scaffold quality), NOT the hand-match floor.", "",
"## Routing summary (by lever, reach-weighted)", "",
"| lever | fns | reach-134 | Σ reach | what it is |", "|---|---|---|---|---|"]
desc = {"WAVE": "Ultracode swarm + §17 toolkit + canon-first gate (the yield engine, T6)",
"STRUCT": "m2c blocked on a type (fn-ptr/jump tables, struct deref) — needs type context",
"PINS": "regalloc/schedule near-miss — register-pin hand-match; class-crack pool (T3)",
"STUB": "fundamental loose-typing (ARITY_WALL) / non-faithful — honest INCLUDE_ASM (P9)"}
for lev in ["WAVE", "STRUCT", "PINS", "STUB"]:
g = by_lever.get(lev, [])
r134 = sum(1 for x in g if x["reach"] >= 134)
sreach = sum(x["reach"] for x in g)
L.append(f"| {lev} | {len(g)} | {r134} | {sreach} | {desc[lev]} |")
L.append("")
# WAVE pool, reach-134, ranked (T6 fuel)
wave134 = sorted([x for x in by_lever.get("WAVE", []) if x["reach"] >= 134],
key=lambda x: (-(x["reach"]), x["nins"] or 9999))
L += ["", f"## WAVE pool — reach-134, ranked (T6 fuel; {len(wave134)} fns, smallest first)", "",
"| addr | nins | bucket | reach |", "|---|---|---|---|"]
for x in wave134[:a.top]:
L.append(f"| {x['addr']} | {x['nins']} | {x['bucket']} | {x['reach']} |")
if len(wave134) > a.top:
L.append(f"| …+{len(wave134)-a.top} more | | | |")
# PINS / class-crack candidate pool, reach-134, smallest m2c-mismatch first
pins134 = sorted([x for x in by_lever.get("PINS", []) if x["reach"] >= 134],
key=lambda x: (x["mismatch"] if x["mismatch"] is not None else 999, x["nins"] or 9999))
L += ["", f"## PINS / permuter-class — reach-134 near-misses ({len(pins134)} fns; class-crack candidate pool)",
"", "| addr | nins | m2c-mismatch | reach |", "|---|---|---|---|"]
for x in pins134[:a.top]:
L.append(f"| {x['addr']} | {x['nins']} | {x['mismatch']} | {x['reach']} |")
if len(pins134) > a.top:
L.append(f"| …+{len(pins134)-a.top} more | | | |")
# the named T3 class exemplars + their census row + reach
rowmap = {x["addr"]: x for x in rows}
L += ["", "## Named class-crack exemplars (T3 — the Max spikes)", "",
"| addr | class | census bucket | nins | reach |", "|---|---|---|---|---|"]
for addr, note in CLASS_EXEMPLARS.items():
x = rowmap.get(addr)
if x:
L.append(f"| {addr} | {note} | {x['bucket']} | {x['nins']} | {x['reach']} |")
else:
L.append(f"| {addr} | {note} | (not a current stub — matched or split) | | |")
# STUB honesty tally
stub = by_lever.get("STUB", [])
from collections import Counter
sc = Counter(x["bucket"] for x in stub)
L += ["", "## STUB residual (honest, no lever — P9)", "",
f"{len(stub)} fns: " + ", ".join(f"{b}={n}" for b, n in sc.most_common()), ""]
open(ROOT / "docs/exemplar_curriculum.md", "w").write("\n".join(L) + "\n")
print(f"wrote docs/exemplar_curriculum.md + .run/exemplar_routing.json")
print(f" {len(rows)} residual stubs; WAVE {len(by_lever.get('WAVE',[]))} "
f"(reach-134 {len(wave134)}) | STRUCT {len(by_lever.get('STRUCT',[]))} | "
f"PINS {len(by_lever.get('PINS',[]))} (reach-134 {len(pins134)}) | STUB {len(stub)}")
if __name__ == "__main__":
main()