tools/journal_notes.py mines the agent journals per (binary, fn) and appends a
PAST ATTEMPTS section to the pack; claude_wave_packs.py calls it automatically, so
it is the default rather than a step to remember. Idempotent, and R48-safe (a note
stamped with a different binary is never served — §238 homonyms).
Measured before adopting (S71 wave 1, 50 one-agent workflows over the 210-function
real frontier where every target had already refused an earlier wave):
* 38/39 MATCH at closeness 0 (97.4%) vs S70's 124/131 (94.7%) on an EASIER pool
* 29/39 agents cite a prior attempt as what they used
* 4/39 banked by RECOVERING a body that already matched, from a path a note named
* 11/39 matched on the first compile
The two costs it removes are re-testing a measured-inert lever (§406 lists twelve,
§407 fifteen, §410 four — each paid for by an agent and never seen again) and
re-deriving a body that already exists on disk.
Also: jr_isolate_all places file-local `static` definitions with the region that uses
them instead of refusing the whole file. A `static inline` helper (§82.1) has no
address by construction, which is not a defect; the R32 guard was refusing these and
blocking the isolate on 4 of the 6 overlays whose CARVE-REFUSED functions it is the
named remedy for. Two regions using one static is still a hard refusal (duplicating a
used static is a byte change, R43).
docs: cookbook §411, wave-playbook step 3b, accelerators entry.
§322b — the carve class is COMPLETABLE, and every worktree CARVE-REFUSED was an
instrument verdict (.run/sig.<b>.jsonl is gitignored, absent from worktrees, so
jr_inventory read every carve as UNOWNED). build_carve's refusal is EXACT, not
conservative — one object emits one contiguous .rodata — and the real fix
(isolate into its own subseg) already exists and harvest_verify already runs it.
Live census: 71 non-contiguous of 123 jtbl stubs; 21 of those are twins of
already-banked bodies (3,852 ins) free at ~25s each. End-to-end byte-proven in
23 seconds. Remaining blockers are 18 overlay_src_split plumbing defects (<=30
lines each) plus a jr_isolate_all port for main.
§332b — the §332 "walls" are a per-OBJECT assembler mode, not a C limit. A 3-line
maspsx reorder-passthrough + as -O2 is byte-INERT across the whole 800c3/800c2
objects and yields 0 diffs for SIX walls whose drafts already exist. That turns
"permanently unbankable" into a per-object Makefile switch and retires
oracle_reorder.py. Only 13 of the 15 listed walls are even reachable.
§378c — a FIFTH decl-blocker variant: the DRAFT redeclares a type/data/callee the
TU or a header already owns. Fix the draft to the TU's spelling (§367), never the
reverse. Two "integration-blocked" rows were phantoms, one of them my own
--any-proto pre-pass breaking a sibling TU (variant 4, second bite).
accelerators #19 — a verdict recorded inside an isolated environment describes the
ENVIRONMENT. Isolation exists so the worker sees less; every gitignored input is a
difference it cannot distinguish from a genuine rejection, and it writes that
difference down once per function. Negative-control the environment with a
known-good item; assert the worker's inputs; report a missing input as MISSING,
never as a verdict.
tools/seed_ref.py gains --contained/--contained-control: an open stub that is a
banked body plus or minus WHOLE BLOCKS — the class edit distance ranks badly.
Branch-offset masking was required (unmasked offsets veto exactly the target
pairs) and a min-side-25 floor (89% of raw hits were prologue/epilogue vacuity).
Ranks by (substitutions+regions, cover), not by d. Controls: planted-deletion
positive 60/60, random-pair base rate 0/397, R32 population 346/346, and a
post-refactor --near regression reproducing the stored slice exactly.
Banked on first use: ov_SC01_077/func_80184D50 = banked ov_SC03_007/func_8018283C
minus its trailing `&= 0x7FFFFFFF;` — MATCH, closeness 0, 98/98.
* cookbook §390: minimum distance is not minimum work (rank by effort; a deletion
is free, a substitution is thought), the lookalike filter r = d/min(nins) ~ 0.3
(17 of 30 "cousins" were boilerplate coincidence), and the three fleet-wide
nulls that close the scanner question — 0 new / 9 / 2. Spend integration
effort, not scanner effort.
* cookbook §391: a byte-aligned struct copies in FOUR instructions (lwl/lwr/swl/
swr), a word-aligned one in TWO. Never invent an aggregate type to make a draft
compile — an invented word-aligned Blk8 lost exactly 8 ins across two copies and
read as a believable "near, closeness 70" codegen residual.
* accelerators #18: a claim derived from BYTES is not a claim verified by a
COMPILER. Every similarity/correctness claim must name the tier it reached
(stream containment / compiled standalone / whole-binary gate / clean fleet);
a report that says "verified" without one invites the strongest reading.
Non-reproduction is a finding — say so rather than assuming your own setup.
* playbook §2a-2: the twin ladder (exact -> RELOC-ONLY -> CONTAINED -> cousin ->
cold), take the cheapest tier available, widen only when the tier above is empty.
* SETUP inventory row; generic-decomp-package: rank by work, and stop building
scanners once the well is dry.
The exact-hash twin tier found 22 of 352 reachable open stubs (6%). The
edit-distance band added by `seed_ref --near` finds 75 of 352 (21%) — 3.4x — on a
corpus we believed fully mined. 31 of the new rows were PURE reloc-only twins of
already-banked bodies; 8 banked the same day at ~0 agent tokens, one 94-ins
exemplar serving five open copies.
* cookbook §389: the h_norm hole (norm_stream drops its pending lui-hi on an
intervening R-type, so indexed-global reloc twins hash differently and vanish
from seed_ref/twin_sweep/dedup/family-maps at once). Do NOT fix h_norm — every
stored calibration keys on it; the near tier reads through it.
* accelerators #17: the generalisable law. A similarity hash built for DEDUP
under-matches by design, which is correct for dedup and silently lossy as a
FRONTIER join — the two questions want opposite error directions, and the
frontier failure looks exactly like "this function is unique".
* generic-decomp-package §2b: build the near band at the same time as the exact
tier, with the three verifications. It pays from the first bank for a new
project, where we paid a session to recover the debt.
* SETUP inventory row + playbook §2a (run it before believing any "no twin"
verdict; never send a RELOC-ONLY row to a drafting agent).
next-session-triage-ladder.md was still written as a to-build spec. It now leads
with the shipped status, the acceptance numbers, and the three things the spec got
wrong (the '32 free banks' were 0/28; the autodecl arm is worse in-tree than the
raw draft; PRE and POST cannot be the same pass because residual_rules_b needs a
draft), plus the one found by building it — never classify on a moving tree.
accelerators #16: a 'verified, just bank it' claim must name the compilation it
survived. Day-one kit material for a new decomp: any per-function oracle compiles
in isolation, every real bank compiles in context.
#15 — the tool worth building FIRST in any decomp, because it works at 0% and
compounds: run every question down TWO independent paths on a schedule and fail on
disagreement. Ten-plus S68 blockers had one shape — a tool computing a TRUE number
about a NARROWER world than we believed it covered — and EVERY one was caught by
two measurements disagreeing, never by review. R32/R34/R40 already say this and
were not enough: they are rules applied by whoever writes the tool, and in S68 I
wrote R34's warning into one docstring and rebuilt the exact defect it warns about
an hour later in another file.
Includes Drew's scheduling half, which this project only ever did by accident: the
widening is PERIODIC. Tooling is not wrong when written, it goes STALE as new
idioms reveal populations it cannot see. At every phase close ask 'which scanner's
denominator just got wider?' — that question converts new knowledge into free
banks. The §332 sweep is the worked example: one review, 10 fns / 1,027 ins
reclassified, one in-flight escalation stopped mid-spend.
generic-decomp-package.md — what a NEW decomp inherits on day one and does BEFORE
cracking: mine the COMPILER SOURCE and sibling projects for idioms (this project's
best late idioms came from reading gcc-2.7.2's own passes and needed no matched
function at all — week-1 work done in month N), port the families/twins/dedup/carve
layer first, then the oracle harness, and only then crack. With the honest caveat
that tooling-first makes the cheap half free and does NOT shrink the hard tail.
MEASURED (denominators in .run/S67_findings.md):
* 193 of the 530 open functions ALREADY have a draft on disk (1,885 wave targets seen,
1,521 banked, 171 open-no-draft, 166 never drawn). Classified in their real TUs:
37 MATCH / 67 NEAR / 89 CC1-FAIL.
* 159 open functions (30% of the frontier) reference a jump table; 96 are PLAN-REFUSED
by build_carve (non-contiguous same-subseg .rodata), 75 non-main across 38 subsegs.
Not a codegen wall and not a decl wall — carve plumbing.
NEW
* tools/strand_census.py — coverage-asserted census + rtu_match classifier + draft staging.
Keys binary:fn (R48); classifies each pair once after merging every manifest's view.
* tools/o0_detect.py — the -O0 prologue tell extracted from match_one (which parses argv at
import and therefore cannot be imported). match_one re-exports it; ONE definition (R33).
Wiring it into the classifier turned md_MAIN_003 from 8 NEAR (7 of them >20) into 6 MATCH.
Negative-controlled both directions.
* tools/scope_demote_drafts.py — §8d as an _xform-contract gate rung. NOT yet exercised.
FIXED
* jtbl_carve --probe now runs build_carve (a pure planner) and reports plan-refused. It
previously called only island_probe, which answers a necessary-not-sufficient question —
every blocked function probed "carveable", and S66 priced 32 of them as free on that.
* blocker_probe.macro_scope selects the LAST #define per macro name, matching cpp.
engine_core.h has 1,037 duplicate DEFINE_func_ names and 4 with DIFFERENT bodies.
NOT VALIDATED — DO NOT SCALE
* jr_isolate_all: two real defects fixed (carried types deduped by name; header-provided
types no longer re-emitted) but ov_SC02_000 STILL fails the byte gate after them.
Open lead: file_scope_types carries a block without its enclosing #if guard. 20 of 35
blocked overlays dry-run clean and that number means nothing until one round-trips.
0 functions banked this session. tools-health has ONE pre-existing cdecl defect
(1 of 74,749 declarations, func_8017EE08_p55352/struct ZnRec) — cdecl.py and its inputs
are byte-identical to HEAD, so it is not from this change.
Knowledge banked: cookbook §322/§323/§323a/§323b, decision-log pivot, accelerators #13/#14.
R30/R31 capture while hot: the resolver pivot (63 zero-token banks of 245 staged of 424 judged of
1,352 nominated), the RED-fleet finding (15/214 baseline-RED refusing 174/182 doubly-verified
drafts), the three byte-proven repairs so far, and rule candidates R56–R58.
Drew's endgame deliverable is a workflow system another person can run solo on any
target, any compiler. We had three docs recording BFM's history (accelerators,
decision-log, automation-runbook) and none stating the SYSTEM. This is that document,
written to one rule: if it would still be true for a different console and a different
compiler, it belongs here.
Contents: the byte gate as the only arbiter and the oracle ladder around it (each
oracle must state its own blind spots); lanes and why the clock-limited one is never
stopped to ship a change; the CARD as fuel rather than a ticket, including the lever
lesson (a label a worker cannot look up is a dead end — 108 transcripts searched for a
word our knowledge base did not contain); draw-time refusal and the four measured
instances of the dominant defect class; free work before paid work; giving an excluded
population its own lane instead of an exclusion; model routing and per-lane budgets;
the flywheel with the one-wave lag and the inert-rider law (1 in 3 credited levers is
byte-inert, measured twice); the economics as measured; what transfers vs what does
not (the knowledge base is per-compiler, the machine that builds it is universal); and
a bootstrapping order for a new project.
Numbers are stated with their denominators so a new project calibrates rather than
copies.
bash parses a while...done body in full before executing, so a lane-ARG change needs
a fresh shell; a python bounce re-runs the old command line (measured P31 S59: an
18-minute-old edit was invisible to the bounced process). Includes the three-way
table of what takes effect when — code / args / wave-draw defaults.
R42: gate_main reverted 61 byte-proven overlay banks it could not distinguish from its own
substitution (sweep_parallel gates commit=False by design). Fixed by committing overlay banks
before the main batch, chunking main at 8 to bound bisect cost, and replacing every blind
'git checkout -- src/ config/' with commit-or-refuse in ox_campaign and idiom_serial.
R43: sweep_parallel had an explicit branch admitting main, which cannot be gated incrementally
— wave ab banked 0/105 main cards while its non-main cards banked 94/115 (82%), and the wave
read as a drafting failure. sweep_parallel now refuses main and names gate_main.py.
Also: validate_targets now prefers the card's own addr field (named symbols like SYS_OBJ_F00
were MALFORMED and discarded whole 220-card waves); ox_campaign deals model lanes by
smallest-ratio scheduling (a 73-card wave had put 73 shards on ox and 0 on deepseek);
docs/accelerators.md gains the four vacuous-check defects.
- BANKED: 11 functions at 400-952 ins from the cascade (func_8017D898 952, func_8017CE58 733,
func_801902EC 673, func_8018C2D8 673, func_8018A8D4, func_8017C6F4, func_800CBB38,
func_800CF3A4, +3). check-all 213/213 from a clean tree. 6 near = jr/switch (§53 separate
banking step), 1 failed. The cascade agents wrote 6 new cookbook sections incl. §158.
⚠️ tools-health UNVERIFIED at commit (stale cookbook index fixed, confirming re-run
interrupted) — run it first next session. check-all is the byte oracle and it is green.
- WASTE PREVENTION (Drew: "prevent this from ever happening again, however you need to"):
* tools/validate_targets.py (NEW) — names 5 defect classes (NO-ASM / MID-BODY /
OUT-OF-RANGE / ALREADY-DONE / NO-BOUNDARY), exits non-zero.
* WIRED INTO wave_snapshot so it fails closed — every wave passes through there for its .s
files, so no path from target list to spawned agents bypasses validation. Negative-control:
a 3-target bad list is refused with the exact mid-body offset (+72 bytes of 100).
* The cascade `done()` predicate now short-circuits on SKIPPED as well as MATCH. It tested
only MATCH, so a non-existent target fell Sonnet -> Opus -> Fable and three agents each
proved the same phantom absent: ~29 invalid targets x 3 tiers = 87 of 119 agents, ~9.7M
tokens. A tier that cannot act must END the pipeline, not escalate emptiness.
* docs/accelerators.md A9, including that wave_snapshot's own R32 assertion REFUSED that list
(24 of 57 found) and was routed around — the one instrument warning that was right and ignored.
- B RE-SCOPED (S46-10) and deliberately NOT done: the extend blocker is INTRA-HEADER, not
target-side. engine_core.h declares memcpy FOUR incompatible ways across its DEFINE_ macros;
two in one TU collide. NOT a safe cleanup — the in-tree note at ov_MAIN_012.c:14333 records
that `extern memcpy` disables gcc's builtin and turns an inlined block-move into a CALL, so the
declaration CHANGES CODEGEN. Probe one macro in one binary and byte-gate before any sweep.
- C (dedup_extend over the 129) stays blocked on B. Full context for both in the checkpoint.
Drew: "make it more multi-threaded... I still see my cpu idle for far too long."
Measured, fixed, and regression-tested against the S46-3 bank as a KNOWN ANSWER.
- THE MEASUREMENT: 31s saturated (33 makes/48 cc1/load 27) then ~25s with ONE build alive
while 31 cores idled, repeating. Causes: ex.map starts in list order so the giants land
last, and apply/restore is single-threaded.
- gate_all -> gate_failures: return EVERY failure the sweep already computed (~138 rounds -> 1).
- Longest-first gate scheduling; results re-sorted into `changed` order so the verdict stays
bit-identical to the serial loop's.
- PER-OVERLAY INDEPENDENT SEARCH, IN PROCESSES. My first cut used threads and the box refuted
it: 0-4 builds alive at load 3, because the work is regex over 15k-line files and 138
"parallel" searches all queued on the GIL. Same logic in a ProcessPoolExecutor: 14-29 builds,
load 34.75, search phase ~100s. Safe because the shared header is written ONCE by the parent
and each overlay owns its own .c files + build/<bin>/. Seeded with one in-process search
first — a pool submitted at once gives every worker an empty suspect list and makes all 138
pay a full bisection. place_in_overlay extracted to module level so the worker and the
in-process apply cannot drift (R33); compiles_standalone's fixed t.c is per-call now.
- THE REGRESSION (the point, not the stopwatch): revert src/+config to pre-bank, re-run the
identical command -> 29 functions (same), 141 overlays byte-identical, 682s vs ~1440s, and
285 exclusions vs ~350 => +62 MORE member instances (249,161). The old prefix-based
necessity probe was OVER-EXCLUDING (charging 4 fns to 9 overlays that did not all need
them); the per-overlay shrink minimises per overlay. The faster path is also more correct —
a timing comparison would never have shown it. R22 213/213 + tools-health green.
- STILL SERIAL, now the actual wall-clock (neither is a build): ~3min setup before the first
gate (registered_addrs() yaml-parsing a 1949-group/249k-instance registry + 213 sig loads)
and ~2.5min of sequential reconcile_caller_extern after the search.
- Captured as defaults: docs/accelerators.md A8 + memory fleet-tool-parallelism-defaults.
cookbook index regenerated (my §155c append left it stale — the gate caught it, exit 1).
The S45p9 blocker is closed, and the recovery loop that kept it from finishing is rewritten.
- BANKED: dedup_propagate --auto-from ov_SC02_037 --recover -> 29 functions propagated,
141 overlays byte-identical, dedup 1920 -> 1949 groups, member instances 246,284 ->
249,099 (+2,815). make clean && extract-all && check-all -> 213 passed / 0 failed (R22).
- WHY IT FINISHED THIS TIME: gate_all -> gate_failures returns EVERY failure from the sweep
that already computed them, and the recovery loop resolves them all per round. Converged in
3 rounds; the old one-overlay-per-sweep design needed ~138. That reframes the S45 run — it
was not nearly done when it died, it had barely started.
- Batching did NOT cost capability: per-overlay necessity probes excluded four of the nine
culprits from only the 9 overlays that needed it (not all 138), and ov_SC07_006 was
RECOVERED by the Part-B caller-extern reconcile instead of excluded.
- Plan phase parallelised: 5 min -> 26 s, plan + skip classification byte-identical. Its
compiles_standalone temp file is per-call now — the fixed `t.c` was the same fake-isolation
class as match_one's shared --work dir (P28 T5), latent until something ran it in parallel.
- docs/accelerators.md (NEW, Drew 2026-08-07): the reusable-workflow ledger — what we learned
late that a future decomp should know on day one, each entry with when we found it, when it
WAS findable, what it cost, and the honest prerequisite where one exists.