Files
BFM-decomp/.run/s35_capture.py
T
Drew T 3f51101ca9 docs(phase-30): SESSION-33..37 checkpoint — PAUSED; 16 ungated wave-5 drafts preserved in git
Paused at Drew's request for a Windows restart. Nothing running, tree lock free,
tree clean (R23 db churn aside). R22 run 19x this session, 140/140 every time.

THE ONE THING OWED: `.run/s37/*/func_*.c` — 16 wave-5 drafts, all claiming MATCH,
NONE gated. Force-added to git (.run/ is gitignored) because they cost ~2.7M
agent tokens and Workflow's resumeFromRunId cache is SAME-SESSION-ONLY, so it
does not survive the restart. Resume by GATING them, not by re-running the wave.
Also preserved: the wave scripts (.run/s36w.js, .run/s37w.js), manifests, the
hardened gate driver, and the four capture drivers.

MEASURED THIS SESSION (both answer questions Drew asked):
- The wave PROMPT is the lever. Bank rate 76% -> 77% -> 100% -> 100% on the same
  models and the same gate, prompt the only variable. The jump was STEP 0 (a
  magic-literal grep of src/, ahead of engine_core.h) — and that step came from a
  wave-2 agent's index_gap report, i.e. the agents write the next prompt.
- The pipeline() fix, before/after: wave 4 parallel() 14 targets / 136 min /
  2.5x parallelism; wave 5 pipeline() 16 targets / 82 min / 3.8x. 40% faster on
  14% more targets. The two-batch design was a hard barrier with 46-min dead gaps
  at each boundary; the harness already caps at 16 so the batching bought nothing.

Housekeeping: removed 3 stray cc1 intermediates (t.i, t.i.greg, t.s) that an
agent left at the repo ROOT — scratch belongs under .run/ (R12), same class as
the gccdump.lreg noted at the Phase-24 close.
2026-08-04 13:29:51 -06:00

38 lines
2.0 KiB
Python

#!/usr/bin/env python3
"""Capture the whole-binary blocker for a gate-refused draft: splice -> build -> read the
compiler's OWN error -> revert. Agents cannot run the gate, so a TU-level declaration conflict is
invisible to them (§136a: classify on the build's OUTPUT, never its exit status)."""
import sys, os, re, subprocess, shutil
sys.path.insert(0, 'tools'); import corpus
for spec in sys.argv[1:]:
ov, fn = spec.split(':')
addr = int(fn.split('_')[1], 16)
st = corpus.stubs(ov); rec = st.get(addr)
if not rec:
print(f"== {ov} {fn}: NOT A LIVE STUB (already banked?)"); continue
tu = rec.path
draft = f".run/s36/{ov}/{fn}.c"
stub = f'INCLUDE_ASM("{rec.asm_dir}", {fn});'
t = open(tu).read()
if t.count(stub) != 1:
print(f"== {ov} {fn}: stub line not found verbatim in {tu}"); continue
bak = t
open(tu, 'w').write(t.replace(stub, open(draft).read()))
r = subprocess.run(['make', 'build', f'BINARY={ov}'], capture_output=True, text=True)
open(tu, 'w').write(bak) # revert ALWAYS
out = r.stdout + r.stderr
# §136a, applied to MYSELF: a narrow keyword filter is exactly how a real error goes unseen.
# Keep every cc1/ld diagnostic line that names a source position, minus the known SHB noise.
HARD = re.compile(r'undeclared|redefinition|conflicting types|parse error|undefined reference'
r'|syntax error|too (many|few) arguments|invalid|incompatible')
lines_ = [l for l in out.splitlines()
if re.search(r'\.[ch]:\d+|undefined reference', l)
and 'built-in function' not in l and 'Makefile:' not in l]
hard = [l for l in lines_ if HARD.search(l) and 'warning' not in l.lower()]
errs = hard or [l for l in lines_ if 'warning' not in l.lower()] or lines_
print(f"== {ov} {fn} (build rc={r.returncode})")
if errs:
for l in errs[:6]: print(" ", l.strip())
else:
print(" NO COMPILE ERROR -> the draft builds clean; the miss is a byte DIFF at whole-binary")