SESSION-17 filed this as §65g-class: "not 'run one more tool', but 'needs a transform that does
not exist yet'". Refuted. It needed the correct self-declaration.
- The TU expands DEFINE_func_80174C80() carrying `extern s32 func_80174CB0(s32, s32);`, while all
~100 prior drafts defined `void func_80174CB0(s32, s16)` — matches perfectly STANDALONE, dies in
the real TU with `conflicting types`. Defining it `s32 (s32, s32)` and recovering param_2's
s16-ness with an explicit (s16) cast at the func_80012558 use site is byte-identical.
- Drafted by an isolated agent (Opus 5 @ High, 65k tok) pointed at the NAMED blocker with the
canonical callee sigs supplied — not asked to re-derive the C. It self-verified through the real
cpp->cc1->maspsx->as chain (cc1 rc=0, 123/123 ins, 0 diffs) before reporting, so the bank was
first-try clean.
- make check BINARY=ov_SC07_006 BYTE-IDENTICAL (7ca772be); R22 clean-fleet 140/140, 0 failed.
- Propagation ×138 follows as a separate targeted step (§55b: bank -> commit -> dedup_propagate --addr).
- FOLLOW-UP LOGGED: the recovery ladder also relaxed `extern s32 func_80174CB0(s32,s32)` -> `()` in
src/shared/engine_core.h (+2 overlay files), escalating a binary-local bank to FLEET tier. The
banked def AGREES with the original prototype, so that edit looks unnecessary — to be tested.
- func_8012B4B8 (84) + func_80169228 (105) propagated via targeted --addr (--check-only first,
never --auto-from): 138 overlays byte-identical, 2 new dedup groups, ~+26,082 ins.
- R22 clean-fleet: check-all 140 passed, 0 failed of 140. Fleet fn-count 88.90 -> 88.98%.
- The 3 non-banks are diagnosed, not guessed (blocker_probe, both oracles agree): func_801463A0 is
a real-cc1 MATCH in its own TU that the gate still rejects (§65c rtu-vs-gate divergence, link-level);
func_80156670/func_80174CB0 carry "drop when banking" typedefs textually identical to the canonical
ones. Blockers STACK — stripping the cc1-named typedef exposed the next (S8->B8; MATRIX->a callee
conflict). Remedy named: strip ALL shared-provided typedefs, then run the DRIVER's ladder.
- Ladder-only recovery (no demacroize, so these are NORMAL banks that can propagate x138):
func_8012B4B8 (84 ins) + func_80169228 (105 ins), both confirmed gone from src, not read off
the report (§55b trap 4). 2 of 5 candidates.
- DRIFT-CHECK EARNED ITS KEEP (R14): the backlog's close=0 was wrong for 2 of the 7 spine entries —
func_8012CC88's draft is for ov_SC07_006 and is 13 off in ov_SC01_077 (the documented
'backlog drafts are overlay-specific' caveat, now confirmed), func_80158638 is 2 off, not 0.
- The cross-file churn is gate_stage's own fix_arity_callers --any-proto pass on the banked fns'
caller decls (byte-neutral no-proto widening; comments preserved, H5). R22 clean-fleet 140/140.
- Diagnosed the 3 non-banks with blocker_probe (both oracles agree 3/3): func_801463A0 = real-cc1
MATCH in its own TU yet gate-rejected (the §65c rtu-vs-gate divergence); func_80156670 and
func_80174CB0 = local_type collisions on 'S8' and 'MATRIX' -> uniquify (T0, draft-only).
- Targeted `dedup_propagate --addr 0x80177940 --recover` (NEVER --auto-from; --check-only first
confirmed the plan held exactly this one address, so the de-macroize hazard could not apply).
- 138 overlays rebuilt byte-identical; 0 stubs remain for the address; 1 new dedup group registered.
- R22 clean-fleet: check-all 140 passed, 0 failed of 140.
- Fleet: fn-count 88.86 -> 88.90%, instr-weighted 79.6 -> 79.7% (+13,938 ins = 101 x 138),
distinct-code 64,874 -> 64,875 unique fns.
- THE FREE TEST (cookbook §66): reverted func_801778A8's bank to its INCLUDE_ASM stub (stub state
rebuilds BYTE-IDENTICAL 7ca772be — a faithful revert proves itself; needs `make extract` first,
the R22 corollary) and re-banked it THROUGH recover_integration.py --commit --r22.
pass1 1/1 -> exact restore -> pass2 1/1 -> commit commit:0928 -> R22 140/140 -> report.json.
Bank confirmed from SOURCE (stub gone), never the report (§55b trap 4). EQUIVALENCE: git diff vs
the pre-revert commit = ONE blank line (mine) -> the driver reproduced SESSION-16's state exactly.
- DEFECT 1 (SAFETY, found by reading before firing): PROPAGATION is a fleet-tier write
(dedup_propagate --auto-from -> src/shared/engine_core.h + up to 138 overlay .c) that was both
UNDECLARED and the DEFAULT, so --max-tier binary still permitted the widest write in the toolchain.
assert_write_set cannot catch it (it runs before the gate; under --commit git status is clean).
FIXED up front: propagate now requires --max-tier fleet AND --r22, and is REFUSED after a
demacroize stage (those banks are x1 by construction; --auto-from would re-macroize and undo them).
Both refusals negative-control-tested, exit 1. The "standing hazard" is now a refusal.
- DEFECT 2 (METRIC): gate_stage scraped the fleet % via a progress.py label that no longer exists ->
fp=None -> 50 gate commits recorded "fleet None%". Now reads FLEET instr-weighted (legacy fallback
+ loud stderr warning if neither matches); parses 79.6.
- STALE DIGEST (R14): docs/progress.fleet.md at HEAD disagreed with HEAD's own source by 45 in the
dedup-shared column — generated during the §65g local_type trial whose edits were then reverted.
Regenerated (reproduced identically in-gate + standalone); headline %s unaffected.
- cookbook §66/§66a/§66b distilled in-session (R30); SETUP.md gains the missing recover_integration
row (R21 debt). tools-health OK: corpus 0/0, cdecl green, audit-binaries 140 citizens, lint OK,
dedup-check 1879/0. Fleet unchanged 79.6% instr / 67.7% distinct / 88.86% fn-count.
- func_8012F40C banked (the callee-conflict variant): relaxing demacroize from "the draft's own
function" to "any decl the DRAFT declares incompatibly" reaches macros that declare a CALLEE
differently than the draft does (RotTransPers/RotTransSV). 14 banks total, R22 140/140.
- THE ONE FAILURE, kept honest: func_8012F49C was rtu-MATCH but the whole-binary gate REJECTED it.
rtu_match is relocation-masked, so a wrong call TARGET is invisible to it -- and this was a callee
case, exactly where the mask hides the error. Trust rtu MATCH for self-decl corrections, distrust it
for callee ones (§65c). Reverted its edits and re-banked only the winner rather than leave
byte-neutral churn on matched code (§57a-4).
- DISTILLED IN-SESSION (R30/R16/R31/R21): cookbook §65 + §65a-§65e (blast-radius tiers; the
de-macroize escape and the §20 refutation; the rtu-vs-gate divergence; the existing-ladder baseline;
two-oracle practice); decision-log entry with the HONEST multiple (~2.3x, not the projected 3.7x,
and it lands on distinct-code not the display number); calibration.md measured table; SETUP.md rows
for blocker_probe + demacroize PLUS the three the inventory was missing (lift_types, uniquify_type,
fix_header_decl-as-retired).
- Carried and NAMED, not dropped: 10 match_one-MATCH drafts still blocked by stacked classes, and the
11 `near` drafts which are unfinished drafts, not recovery fuel.
Every real-TU rtu_match MATCH converted to a whole-binary bank: 13/13, 0 failed.
- BANKED (all BYTE-IDENTICAL, whole-binary gate, stub-gone confirmed by grep not by report):
func_8012CC88 func_80138DE0 func_80144B14 func_80146750 func_80147364 func_8014CF04
func_8014D12C func_8014D610 func_80161374 func_8016163C func_80161774 func_80161888 func_801778A8
- Mechanism: existing draft-side transforms (cast_call_sites + reconcile_tu) then tools/demacroize.py
expands the conflicting DEFINE_func_* instantiations in the overlay's OWN TU with the self-decl
corrected to the draft's byte-true signature. Writes confined to src/ov_SC07_006/**.
- R22 clean-fleet after the batch: 140 passed, 0 failed of 140. Write-set asserted T1 (3 TU files).
- METRICS, honest: distinct-code 64,860 -> 64,873 unique fns (+13) -- the FULL credit, since
progress.py marks an h_exact class matched if ANY instance is. instr-weighted 79.6% and fn-count
88.86% are ~flat, because a de-macroized bank is x1 and cannot propagate x138. That price was
stated before the work, not after it.
- dedup-check 1879 validated / 0 failed; 0 NON_MATCHING in any default build (G4).
- 5 of the 6 s15 fresh cores propagated ×138 (func_801483E8/8014680C/8017129C/80177AD4/801759D8;
func_8014A51C §20-capped). R22 clean-fleet 140/140. fn-count 88.66->88.86%, instr 79.4->79.6%,
distinct-code count 64854->64860, dedup 1879/0.
- EFFICIENCY AUDIT (decision-log): the 2 LLM waves ran 92% match_one MATCH but only ~27% whole-binary
bank; 6 spot-checked non-banks are ALL match_one MATCH (byte-correct bodies). NOT a missing idiom —
an INTEGRATION wall (def-side sig / data-extern / unshared struct). We strand ~16 paid-for correct
functions per wave; a fleet-safe integration-recovery pass would ~3.7× yield for 0 new drafting
tokens. Next investment = integration tooling, not more drafting. Waves held per Drew.
The grinder ran the targeted permuter sweep to EXHAUSTION (all 75 permuter-shaped candidates;
correctly skipped 1575 redraft/structural/integration). It banked 29 distinct functions autonomously
(gate_stage commit=True, byte-gated, fail-closed, §55b un-propagated), 39% conversion.
- All 29 are LOW-REACH (1-5) overlay-unique code in the 0x8017-0x8018 range — confirming the map's
finding that the permuter-admissible set is the low-leverage tail (the high-reach near-misses like
func_8014F3E8 close=1 reach=134 are redraft/structural, NOT permuter-shaped).
- Propagation of the 22 reach>1 banks filled only 1 (0x80180710 ×2); the rest are genuinely
overlay-unique (siblings byte-diverge) — as predicted.
- R22 clean-fleet 140/140 (the 27 overnight per-binary-gated commits verified fleet-wide, §61).
- distinct-code 64837 -> 64854 (+17 unique fns); session total +22 unique (wave +5, permuter +17) —
the first real distinct-code progress in many sessions. instr 79.4%, fn-count 88.66%, dedup 1874/0.
- Propagated 0x8012A464 / 0x8014FFDC / 0x801502EC -> 138/138 byte-identical, 0 stragglers, 3 new
groups. R22 clean-fleet 140/140; dedup 1872/0; C1 237654/237654.
- FINDING (R14/R31): the §20 propagation cap was gating source-level DE-DUPLICATION, not coverage.
The whole uniquify campaign (Buf+MATRIX+Vec8, 223 files renamed, ~1559 copies stripped, 5
propagations, 4 R22 cycles) moved the fleet by +6 functions / +558 ins / -6 stubs and 0.00pp on
all three headline metrics. The freed cores' members were ALREADY matched individually;
propagation just consolidated them into shared macros. "Unblocked" != "unmatched".
- SESSION ATTRIBUTION: of -837 stubs / +0.3pp instr / +0.23pp fn-count, -831 stubs came from the
FIRST batch (broad lift -> 13 cores). The uniquify campaign contributed -6.
- Roadmap B4 re-labelled: a maintainability item, not a coverage lever. Remaining camps
(Handler/Blk8/V8/Prim/Prim_8016E7C8) are small and now known low-yield — opportunistic only.
- distinct-code sat at EXACTLY 3811442/5634875 = 67.6% at open and close. Fresh cracks are the sole
mover of that number; point the next session there.
MEASUREMENT CORRECTED THE PLAN. The checkpoint called for a "per-camp field-access reconcile";
measuring the camps refutes that: Vec8 = {s32 w[8]} (32B) in 180 files AND {s16 unk0..} (8B) in
139 files; MATRIX 48B/32B/32B; Buf 16B / 0x20+ / DrawEnv. These are DIFFERENT types sharing an
identifier across TUs of the same overlay — reconciling to a canonical layout MERGES them, the
same failure that broke 103 binaries on Prim. The right op is UNIQUIFY: rename the non-majority
camp (byte-neutral — a type name emits no code; TU-local by construction), which makes every camp
single-def and liftable by the existing lift_types rules.
- NEW tools/uniquify_type.py: deterministic camp ordering (file-count desc, then normalized text,
so re-runs assign the same suffixes); majority keeps the name, camp n -> <T>_c<n>; rewrites ONLY
files that DEFINE that camp (a file that merely USES the name gets it elsewhere and is untouched);
\bT\b word boundaries so `Buf` never matches `Buf80153978`.
- VALIDATED on Buf (578/6/1 files): 11 identifiers across 7 files -> 3 camps LIFTABLE -> lifted
(585 local copies stripped) -> R22 140/140 -> blocked core queue 13 -> 11 (0x8012ea90, 0x801749c8
freed). Propagated 0x8012EA90 ×138; 0x801749C8 dropped (straggler in ov_SC07_006).
- YIELD, HONESTLY (P9): ZERO new matched functions. fn-count 88.61% / instr 79.3% / stubs 40281 all
UNCHANGED; dedup 1867->1868, C1 +138. 0x8012EA90's members were ALREADY matched in all 138
overlays — the propagation consolidated duplication into one shared macro (DRY), not coverage.
The value is the PROVEN RECIPE + the queue moving 13->11, not the numbers.
- dedup_propagate (R32): the skip line printed a COUNT and no names, and aggregated three unrelated
causes into n_local — a body skipped merely for a `//` comment (macro-unsafe, 1-line fix) read
identically to one genuinely using an overlay-local type. Now named and split by cause.
- cookbook §64a (uniquify-vs-reconcile + the validated recipe + remaining camps by cost).
With the §20 local-type cap lifted (commit:0863), dedup_propagate --auto-from planned 17
self-contained cores that were previously skipped "not self-contained (local types)".
- BANKED: 12 cores via --auto-from + func_80175308 (propagated separately, 138/138) = 13 ×138.
func_80175308 is the PROVABLE unblock — the core the SESSION-13 checkpoint named as
local-type-blocked. No claim is made that all 17 were unblocked by the lift; measuring that
needs a pre-lift re-scan I did not run (P9).
- 5 correctly DROPPED as cross-overlay stragglers (0x8012A018, 0x80172C50, 0x80173A60,
0x80144090 in ov_SC01_000; 0x801495C4 in ov_SC07_006): h_exact sharing is all-or-nothing and
those overlays' bytes diverge. --recover NOT used (the documented quadratic thrash hazard).
- GATES: R22 clean-fleet 140/140 BYTE-IDENTICAL (2nd full cycle this session); make report green;
dedup-check 1854 -> 1867 validated / 0 failed, C1 236964/236964; 0 NON_MATCHING (G4).
- FLEET: instr 79.0 -> 79.3% | fn-count 88.38 -> 88.61% | INCLUDE_ASM stubs 41112 -> 40281 (-831).
distinct-code stays 67.6% — correct: propagation replicates already-distinct-matched code;
only a fresh crack moves that number.
- STILL BLOCKED: 13 cores "not self-contained (local types)", blocked by exactly the 8 deferred
VARIANT entities (MATRIX 3-def, Buf 3-def, Vec8, Prim, Handler, Blk8, V8, Prim_8016E7C8).
Next lever = a per-camp FIELD-ACCESS RECONCILE, not a lift (lifting them blindly is what broke
103 overlays earlier this session).
Crack wave w9lidyi5b (24 fresh LIVE=138 families): 20 self-assessed MATCH, 3 near.
Banked x1 (R22 clean-fleet 140/140):
- 2 self-contained via plain harvest_verify: func_8012B4B8 (§52b-wall crack),
func_80169228.
- 5 via gate_stage's reconcile ladder (cast_call_sites in the draft's own TU):
func_80175308, func_8012E138, func_80130C08, func_8012A1BC, func_80137178.
Correction (decision-log follow-up): fix_header_decl v1/v2 is FRAGILE for shared
multi-caller decls — rewriting an engine_core.h decl breaks callers that use the
return differently (CC1-FAIL). func_8014CD80 was a lucky single-caller/ignored-return
case. gate_stage's call-site-cast is the right tool for multi-caller plumbing (banked
5 where fix_header_decl broke the build). Remaining ~13 near/deeper-plumbing drafts
staged in .run/drafts-sc07006-fresh/. Propagation x138 next.
Bounded probe (SESSION-13, token-free) that REVERSED the same-session "fresh
reach-138 well is spent" verdict. Target func_8014CD80: 138 live, 0 matched, NO
DEFINE macro, a universal body (only universal callees + param offsets, zero
overlay-local D_* refs), clean MATCH draft from batch-1.
- Blocker was a def-side header decl: engine_core.h DEFINE_func_8014CD0C()
forward-declares it `void func_8014CD80(s32,void*,void*)` while the byte-true
def is `int func_8014CD80(s32,u16*,u16*)`. gate_stage's arity pre-pass is
param-COUNT-only (misses return/ptr-type); §54 reconcile_def_sig fixes the
wrong direction.
- One byte-neutral header edit (void->int, void*->u16*; call site passes u16[3]
arrays + ignores the return -> codegen unchanged) -> harvest_verify banked x1
BYTE-IDENTICAL -> dedup_propagate --addr propagated 138/138 overlays
byte-identical (live 138->0) -> R22 clean-fleet 140/140.
- Fleet 78.7->78.8% instr, 88.22->88.26% fn-count from this one family;
tools-health green (dedup 1851/0).
Quantified market (decision-log 2026-07-23): of the 75 fresh (>=100-live)
families, 46 carry an engine_core.h caller forward-decl, 38 SIMPLIFIED = the
func_8014CD80 pattern -> each a candidate x138 (~+1.5-2.8pp instr). NEXT: build
tools/fix_header_decl.py + a fresh-family wave. func_80165CA0's 0/135 was a
non-universal BODY (different failure mode), not this blocker.
Propagation of the 6 batch-1 x1 banks (§55b: banks committed first in commit:0848,
then targeted propagate as a standalone step):
- dedup_propagate --addr: func_801325B8 -> +3 onboarded-tail siblings
(ov_SC07_007/010/011). func_8014A048/func_801678F0 byte-diverge in the SC07
cluster (kept x1); func_8014FE60/func_80167540 local-type-blocked §20 (x1).
- func_80165CA0: consolidated its h_exact subgroup (dedup group registered, +0
new), then family_sweep --hseq 0/135 — a PER-MEMBER WALL (cf func_80133AB0
0/136). The x135 "fresh family" prize does not exist here.
- Net batch-1 yield ~9 newly-matched functions; fleet 78.6->78.7% instr, distinct
flat; ov_SC07_006 84.6->84.8%. R22 clean-fleet 140/140; tools-health 1850/0.
The finding (R14/R35, decision-log 2026-07-23): nins*reach leverage over-counts —
rank by LIVE-siblings. build_wave_args.py --rank live now ranks by the true lever
and reports the fresh(76)/onboarded-tail(44) split. The reach-138 family well is
largely SPENT via wave+gate; the fresh families are the hard tail (def-side
plumbing/DIFF/per-member walls), not free x138 fuel.
- batch-1 wave: 25 non-jtbl ov_SC06_018 targets (reach 3-14 modal), 13/25 match_one
MATCH; whole-binary banked 8 (4 plain + 4 via gate_stage --src-file), swept 4 families
-> 30 members across 13 overlays. 5 matches deferred (missing-sym/s58/deeper plumbing);
12 nears are permuter fuel (several close=2/3/4).
- KEY: non-jtbl fns in a jr-split file need gate_stage --src-file <the jr TU> (the default-
TU reconcile misses them -- same class as the jtbl --src-file fix).
- BUG FIX (R33): gate_stage's arity-undo snapshotted src/<bin>/*.c BEFORE _gate1 splices
the banks there, so an unbanked draft in the batch triggered a snapshot-restore that
SILENTLY REVERTED the banks (measured: a 9-draft run banked 4, the 5 unbanked reverted
all 4 to INCLUDE_ASM). Fix: restore ONLY src/shared/ (the fleet hazard the snapshot
exists for); the binary's own TU arity edits are local + byte-neutral. GATE_NO_ARITY=1
was the interim workaround. s61's law from below (undo scope must not EXCEED write scope).
- incremental check-all 140/140 (concurrent with batch-2 drafting; full R22 after batch 2).
fleet distinct 67.5->67.6% (+38 unique fns), instr 78.6% steady.
- func_8017D648 (102, reach 82, MODAL/cross-address family): cracked fresh in ov_SC06_018
(+ a byte-neutral s17a-1 callee-cast reconcile of func_8012F14C to the TU's 1-arg
convention), banked x1, then swept 70/82 siblings (85%) via family_sweep --hseq
--source ov_SC06_018 --allow-pins (+3 gate-fail, +8 remap-refused unresolved-immediates).
- 3rd data point for the family-specific finding: across 3 thesis families the fresh-
exemplar sweep rate is 100% (func_801365B8) / 0% (func_80133AB0) / 85% (func_8017D648).
Refined model (-> decision-log): the sweep works for the MAJORITY of families at high
per-family rates, with a genuine per-member-wall minority; cracking is the generator.
- R22 clean-fleet 140/140 byte-identical; tools-health green; 0 NON_MATCHING.
fleet 78.5->78.6% instr / 88.18->88.20% fn (session net 78.4->78.6 instr / 67.1->67.5 distinct).
- binary-aware crack wave (new tools/workflows/wave_binary.js): 8-target calibration
over ov_SC06_018 substantial stubs, 7/8 match_one MATCH
- func_801365B8 (155, reach 133): cracked FRESH in ov_SC06_018, swept 132/132 siblings
via family_sweep --hseq --source ov_SC06_018 --allow-pins -- SESSION-10 refused this
family 0/133 from an ov077 exemplar. THESIS CONFIRMED (fresh exemplar unlocks it).
- func_80133AB0 (137, reach 137): cracked fresh + banked x1 (+ a byte-neutral s17a-1
cast reconcile of banked caller func_801343C4), but the family sweep FAILED 0/136 even
from the fresh exemplar (reverted clean) -- THESIS REFUTED for this family.
- FINDING (R14/R31 -> decision-log): the fresh-exemplar sweep is FAMILY-SPECIFIC, not a
blanket mechanical x137. A fresh crack is necessary but not sufficient; the byte-gate
arbitrates each family (~50% on this 2-family sample -> discount the ~1.5pp estimate).
- tooling (R33): family_sweep --source override now searches matched_members (a fresh
member leaves 'members' after a sig-regen); cdecl._depth0_spans consumes backslash
line-continuations so a raw-draft #define macro no longer trips audit-cdecl.
- R22 clean-fleet 140/140 byte-identical; tools-health green (dedup 1849/0, C1 234615);
0 NON_MATCHING. fleet 78.4->78.5% instr / 67.1->67.5% distinct / 88.14->88.18% fn-count.
The contract requires all three headline metrics to include the main EXE. Since
Phase-27 T10 main was reported as a SEPARATE provisional line, so the headline
silently measured 139 of 140 binaries — and flattered itself by omitting the
LEAST-decompiled one.
RESTATED CAVEAT (the old "stale, PROVISIONAL" wording was misleading): main's sig
is Ghidra's (2026-06-14), but function BOUNDARIES derive from the original bytes
and do not change, and matched-vs-stub comes from the LIVE corpus.stubs — so the
numbers do NOT drift. The real limitation is R34: sig_image cannot independently
validate a PS-X EXE's boundaries, so main has no SECOND, DISAGREEING oracle for the
PHANTOM/TRUNCATED class. The sig also excludes the LINKED PsyQ objects, which is
exactly right for a GAME-CODE contract.
EFFECT — the headline DROPS, which is the point:
instr-weighted 78.7% -> 78.4% (10,299,493 / 13,141,652)
distinct-code 67.9% -> 67.1% (3,782,990 / 5,634,875)
A continuity line reports the ex-main figure so pre-2026-07-22 readings stay
comparable, and the binary-count label is corrected to "main + resident + 138
overlays" (it read "resident+139 overlays").
Metrics-only change; no build impact (ov_SC06_018 re-verified BYTE-IDENTICAL).
burndown.py averaged the last 3 INTER-COMMIT deltas. The phase's ROI criterion is
"per-SESSION yield floors out", and historically one snapshot was taken per session
— but I seeded THREE inside this session (9, 9b, 9c). Averaging them drove the mean
to +0.23 and printed "AT THE FLOOR — consider closing P29" for a session that
actually yielded +0.7pp instr (78.0 -> 78.7), comparable to recent sessions.
I nearly closed the phase on it. Same error class as everything else this session:
an instrument answering a DIFFERENT QUESTION than the one asked, where the wrong
answer is indistinguishable from the right one.
- --session-close marks a snapshot as a session boundary; the floor verdict is now
computed ONLY from those (older records predate the flag, so a label containing
"close" counts too). Mid-session snapshots still record for tracking.
- honest output now: "0 SESSION-to-SESSION delta(s) logged — need >=3 for a floor
verdict (1 session-close snapshot on record)".
=> P29 must NOT close on ROI grounds yet: the floor is UNDETERMINED and needs 3
session closes to become computable. The eyeballed "+2.5 -> +1.1 -> +0.6 -> +0.2"
trend is not the instrument's verdict either.
gate_stage._jtbl_prepare carried the SAME config-only undo as harvest_verify's did,
and ate the tree again on the first ladder run: 5 orphan region files, truncated
TUs, `undefined reference to func_80192F64`. That INVALIDATED the run's 0/10, so it
was re-measured rather than reported (R35 — a probe from a broken tool is not
evidence). Tree restored from HEAD and re-verified byte-identical first.
DELETED, not patched (R33 — the best outcome is a deleted stage). It was wrong on
two independent axes:
1. §61b already byte-proved THE CARVE MUST FOLLOW THE SPLICE. A batch pre-pass
carving unspliced functions reports "prepared" and yields a spec that fails
once the body lands — which is why it banked nothing.
2. Its undo snapshotted only config/, while jr_isolate_all rewrites region 0 back
over the ORIGINAL src/<ov>/<nm>.c truncated.
harvest_verify's per-draft prep is the correct mechanism, snapshots the full source
set, and undoes per function. Two implementations of one capability, the outer one
ineffective AND destructive.
THE HONEST RE-MEASUREMENT (clean tree; tree verified clean after):
- 0/10 bank, but 9/10 now COMPILE and land as whole-binary byte-DIFF; 1/10 plumbing.
- match_one close=0 on several (the function's own bytes exact) and rtu_match says
MATCH-in-real-TU for func_80135888 — while func_801299C8's transformed draft does
not compile in its real TU at all. The residual is MIXED, not uniform; at least one
is an IMAGE-level effect rather than the draft or its TU decl context (prime
suspect: jtbl/rodata carve placement). NOT generalized from one data point.
- This PRICES Task 14 stages 2-3 by measurement: the existing ladder converts 0 of
10, so they are not "wire in normalize_self_decls + the type-lift and collect ten
banks" — the projection error §57a already caught once this phase.
- R22 clean-fleet 140/140 BYTE-IDENTICAL with the giant func_8018F694 banked and the
func_80135A4C family swept 138/138
- cookbook §61d (the tree-eating undo in two tools; the constant-label defect; the
re-probe + ladder measurements; the general rule: an undo whose scope is narrower
than its write scope destroys work no byte-gate can see)
- decision-log + CURRENT_PHASE updated (R30/R31)
The session-7 checkpoint gated the entire jtbl track behind one finding: the
carve+isolation path yields a bank that is incrementally valid and clean-invalid
(139/140, [FAIL] ov_SC06_018, "twice, identically"). The prescribed diagnosis
(diff the incremental vs clean object set) never ran, because the failure does
not reproduce.
MEASURED, with the bank applied through the single-function automated path
(harvest_verify --chunk 1 -> [jtbl] carved -> + chunk(1) -> BYTE-IDENTICAL):
per-binary clean (rm asm+build; extract; build) -> BYTE-IDENTICAL cbbc4f44
make clean && extract-all && check-all (run 1) -> 140 passed, 0 failed of 140
make clean && extract-all && check-all (run 2) -> 140 passed, 0 failed of 140
ATTRIBUTION (best-supported; the failing tree is gone): the 139/140 runs were
taken on the tree left by the BATCH _jtbl_prep (6 table-bearing -> 1 carved,
4 isolate-FAILED, 1 stale-asm carve fail) — five failed preps' residue of
stranded carves + half-applied isolations. The per-function snapshot-restore
that removes exactly that residue landed AFTER those runs, in commit:0803, the
same commit that named the blocker.
THE LESSON (R35 on ourselves, -> decision-log): "twice, identically" was not a
replication — two reads of the SAME contaminated state is one observation. A
replication must RE-CREATE the state, not re-run the check. Standing guard:
re-apply a fault from a known-clean tree before writing it down as a property
of the mechanism. Sixth "structural wall" to resolve to our own tree/tooling.
- BANKED: func_80135A4C (181 ins) x1 in ov_SC06_018 — isolated into its own
code subseg + .rodata carve (single-table, no JTBL_PADS; tail3..tail18 renumber)
- §61c faults 1-2 STAND: a stranded carve poisons the overlay; per-function undo
is unsound in a batch -> ONE jtbl draft per harvest_verify invocation.
jr_inventory's 1:1 ownership assertion was right and is unchanged.
- UNFROZEN: this family = 138 members / PURE / 24,978 ins ~ +0.19pp (jtbl_family_bank,
§53 carve law); the 9 preserved t5wave cracks (Task 14 stages 2-3, §57 plumbing)
- R22 clean-fleet 140/140 x2; tools-health OK (dedup 1848/0, C1 234481/234481,
cdecl 53189/53189, audit-binaries 140); 0 NON_MATCHING (G4)
- fleet 78.0% instr / 66.5% distinct / 87.95% fn-count
- also: preserve the 4 untracked wave-4 .o0 drafts (R20); killed an orphaned cc1
from the Jul-21 session burning a full core for 13h23m
DIAGNOSED, not assumed. The 12-draft integration probe banked 1/12 and reported the SAME
label for 10 of the 11 failures: `conflicting types for built-in function 'memcpy'` — the
§58 red-herring (a WARNING, from an unrelated TU position). Splicing three top-reach
failures individually and reading real cc1 stderr gave the actual causes:
conflicting types for `func_XXXX' 3/3 <- loose-typing ARITY conflict
redefinition of `struct V8' <- a SECOND class (type-lift), stage 2
A banked shared caller macro in engine_core.h declares the function with FEWER params than
its byte-true definition takes (the original calls K&R-style with fewer args than the callee
reads); a C89 prototype makes that a hard error. tools/fix_arity_callers.py --any-proto
already fixes it and was simply NEVER WIRED into gate_stage's ladder (only family_sweep
carried §57). Now wired as a TU-side pre-pass.
MEASURED: 2 of 7 top integration candidates banked (func_8016EFC8, func_80164418, both
reach-138) vs the 1/12 old-ladder baseline. R22 140/140; tools-health OK (dedup 1848/0).
INCIDENT — this stage BROKE 138/140 AND R22 CAUGHT IT (nothing was ever committed):
pairing `--apply --any-proto` with `--revert` for the unbanked drafts corrupted declarations
fleet-wide. `--revert` rewrites ()->(void), which inverts a PLAIN apply but NOT --any-proto,
so an unbanked fn whose real decl was `extern void func_801708B0(void *a0)` came back as
`(void)` — in engine_core.h (included by all 138 overlays) and 6 sites in ov_SC01_077's own
sources. harvest_verify --binary ov_SC01_077 reported BYTE-IDENTICAL and was RIGHT about that
binary; the other 137 were structurally invisible to it. Repaired to the exact lines.
ROOT CAUSE FIXED: the ladder now snapshots every file the pre-pass touches and undoes by
RESTORE + re-apply-for-the-banked-set-only — exact by construction, cannot invent a signature.
NEW HARD CONSTRAINT (cookbook §61): any ladder stage mutating SHARED state must be undone by
snapshot restore, never an inverse transform, and validated FLEET-WIDE (R22) rather than by
the per-binary gate that authorised it. §55b's propagation law, one level down. The planned
type-lift stage edits engine_types.h and inherits it by default.
ALSO FIXED: the first wiring passed only --drafts (the narrow-param FILTER) without the
required --funcs, so the stage exited `no funcs given` as a SILENT NO-OP and the gate reported
0/6 as though diagnosed. sh() does not raise on non-zero exit -> explicit rc check added.
The hindsight-study §7 taxonomy predicts plateaus decompose into missing-transform (the
"highest-value bucket and the whole point"), seed-structural, and genuine-wall. Run against
real plateaus this class produced NO missing-transforms, and the answer needed no LLM.
MEASURED: `length` probe, 20 targets, 1 win. tail 1/6; partial 0/12.
AUTOPSY (read directly from the bytes, 3 partial plateaus):
- func_8017F0C0 / func_801806C8: target has `sltiu $v0,$v0,1` = gcc's codegen for `!x`/`x==0`;
the drafts wrote `(u32)(D_x ^ 1)` which emits `xori`. No local mutation crosses that.
- func_8017FF90: draft stores to arg0+8, target stores to a GLOBAL. Different function.
=> these are WRONG DRAFTS wearing a small closeness, i.e. seed-structural, not a mutation gap.
THE FIX IS THE OPPOSITE OF "ADD TRANSFORMS" — a tighter ADMISSION rule:
- _drift_route: permuter only when |d|<=2 AND explains=="tail" (the shape that measurably
converts). length pool 339 -> 34; permuter bucket 389 -> 84.
- SIZE-MISMATCH: added a PROPORTIONAL test (|d| >= 0.5*nt). max(2,0.15*nt) is far too
permissive on a tiny target — a 2-ins draft vs a 4-ins target read as a near-miss.
permuter_weights needs NO extension for this class.
Transferable (cookbook §60b): raising a search-closer's yield is at least as often about
refusing it unreachable work as widening its mutation set. Same knife as Task-13A's
targeting fix, one cut finer. Drafter idiom recorded: `sltiu rd,rs,1` => `!x`, never `x^1`.
17 unit tests green; corpus re-collected (1654 rows, closeness cross-check clean).
PROPAGATION (§55b, its own targeted batch): dedup_propagate --addr 0x80141B90 --recover
-> "138 overlays byte-identical after propagation"; 117 remaining stubs -> 0; 1 new
dedup group. This was the ONLY one of the 21 directed-run banks worth propagating.
THE REPRICING (R14 — measure a bucket's VALUE, not just its conversion rate):
the directed run converted 27% (21/77) but moved the fleet ~0.03pp, because h_exact
reach of the 21 is: func_80141B90=138, TEN at reach-1 (nothing to propagate), rest 2-10.
Instruction-weighted, the ENTIRE permuter bucket is worth ~0.36pp at 100% conversion.
The mechanism is validated; the fuel was small. Priced frontier (ins-weighted / 13.08M):
LENGTH-DRIFT |d|<=2 472,178 ~3.6pp (339 fns) <- the real permuter-adjacent lever
integration 419,162 ~3.2pp (305 fns) <- Task 14's ladder
WIDTH 71,593 ~0.55pp (45)
permuter (current) 46,571 ~0.36pp (74)
BRANCH-POLARITY 9,462 ~0.07pp (22)
So WIDTH/BRANCH-POLARITY are NOT worth prioritizing; my earlier "~200 candidates"
framing undersold LENGTH-DRIFT 10x and oversold WIDTH.
NEW: permuter_weights._LENGTH profile (perm_temp_for_expr/perm_expand_expr are the only
passes that change instruction COUNT; the reorder/decl-order levers that dominate the
regalloc+schedule profiles cannot, so they are down-weighted here) + residual_class
._drift_route (|d|<=2 -> permuter/`length`, larger stays structural — same class,
opposite tool) + classify() accepts a PROFILE NAME directly (the measured profile beats
re-parsing a free-text label). 17 unit tests green.
grinder: --profile filter (probe ONE residual class's conversion) + a PERSISTENT attempt
ledger. `tried` was in-process only, so every fresh --once run re-permuted the previous
run's losers — the permuter is deterministic given (base.c, target.o), so that CPU can
never produce a new win. Measured: a 20-target probe drew 19 already-tried targets.
Keyed by draft_sig so an improved draft legitimately re-opens the function.
First run of the Task-13A-targeted grinder (--once --batch 8 --permute-secs 90):
targeting: ON — 1665 classified; only bucket=permuter is admitted
targeting skipped 1601 non-permuter candidates
{redraft 707, structural 583, integration 305, unclassified 4, unknown 2}
permuter WON func_80181F78 @ ov_SC03_014 (close was 1) [~6 min]
BANKED 2 (both whole-binary byte-gated, R22 clean-fleet 140/140):
- func_80181F78 (8 ins) — classified DELAY-SLOT / schedule
- func_80141B90 (29 ins) — classified IMM-VALUE / cse
Both were classified bucket=permuter by residual_class BEFORE the run: the classifier
predicted a search-closer could reach them, and one did. First end-to-end validation of
the targeting thesis.
THREE latent defects, all pre-existing, all unreachable while the grinder banked nothing
since Phase 21 — the fix made it win and every one fired at once (cookbook §60a):
1. gate_stage commit path crashed on src=None. `src` is DELIBERATELY never defaulted
(Phase 26-A: a default silently PINS the gate to the main .c), but the commit did
`git add src …` unconditionally -> every caller that omits it (grinder, orchestrator,
idiom_hunt) crashes THE MOMENT IT BANKS. Now `git add -u src/`, which also retires the
`src/ov_*/*.c` filename glob that once omitted 4 R22-verified banks from a commit.
2. _xform ladder dirs (-cn/-cast/-rc/-uni) ACCUMULATE across runs: they held 34 stale
drafts, so the gate processed 34 when the grinder submitted 1, and banked one function
it was never asked to try — which would have been committed under a message naming a
different one. Nothing wrong entered the tree (G3/P9 held; the gate banks only
byte-identical output) but report and work had diverged. Now cleared per run.
3. grinder called gate_stage with the default propagate=True = `dedup_propagate
--auto-from`, the §55b fleet-wide path that timed out at 3600s and left 90/140 overlays
broken — and being INSIDE the gate it takes the banks down with it. Now propagate=False;
banks commit cheap, propagation is its own targeted --addr batch (§55b law).
R22: make clean && extract-all && check-all -> 140 passed, 0 failed of 140.
tools-health OK (dedup 1847/0, C1 234343/234343); 0 NON_MATCHING (G4).
The autopsy (hindsight-study §7) assumed the permuter loses for want of a mutation.
Measured over the whole open backlog, it loses because it is aimed at work a
search-closer provably cannot close.
- NEW tools/residual_class.py: decide a near-miss's class FROM THE BYTES. Decodes each
mismatching MIPS word -> (op-skeleton, register-fields, immediate); drift FIRST (one
inserted insn inflates `closeness` by the tail length), then consistent-injective
register map -> REGALLOC-PERM (§31 S11/RC-3), same-multiset-reorder -> SCHEDULE-REORDER,
DELAY-SLOT, WIDTH/BRANCH-POLARITY/STRENGTH/ADDRESSING/IMM-OFFSET/IMM-VALUE. Every class
routes to a BUCKET = which tool the failure wants. Uncovered opcode -> UNKNOWN, COUNTED
(R32). 16 synthetic unit tests (test_residual_class.py).
- NEW tools/autopsy.py: `collect` materialises the corpus Task-12's telemetry never filled
(1 of 6,169 records had a residual) by recompiling every open draft through the EXISTING
match_one path (R33) — 1,752 drafts in 21s at -j12. `report` -> docs/autopsy.md.
- NEW corpus.o0_sources()/is_o0(): the opt-level oracle DERIVED from the Makefile's own -O0
rules, coverage-asserted. Scoring an -O0 target at -O2 makes the residual 100% artefact
(the trap this phase hit four times).
- R34 cross-check baked in: residual_class's closeness vs masked_diff.structured_diff's,
asserted per row; 1,673/1,673 agree, 0 classifier errors.
FINDING: of the 972 records the grinder's own filter admits, only 75 (7.7%) are
permuter-shaped; 547 are structural and 348 are drafts that are not the function at all.
~92% of the daemon's CPU went where it could not win — the byte-grounded explanation of
"7 banks all-time, all Phase 21, 0 since" (Phase-22 audit). grinder.candidates() now
filters on the measured bucket (1,303 -> 78) and takes its directed profile from the
measured class, not the logged label (91% carry none -> it ran on gcc defaults).
Degrades to undirected if uncollected and says so; --no-targeting A/Bs it.
Two measured corollaries (R14, not projections):
- 699 records rank as near-misses at closeness up to 278 purely from a length artefact:
un-attempted work misfiled as a backlog of hard functions -> new `redraft` bucket.
- a 12-draft gate probe of the `integration` bucket banked 1/12 (11 PLUMBING), so the 306
prices Task 14's reconcile ladder rather than promising free banks. func_80167714
(104 ins, reach-134) banked x1, un-propagated by design (§55b).
Two defects fixed forward:
- masked_diff._common_typedefs() used ONE shared probe path, so parallel match_one
processes clobbered each other: 14 of 1,752 drafts lost in a single 12-way run (0.8%),
silently, in every parallel wave ever run. Now per-PID.
- gate_stage.match_one_closeness never passed --o0 -> phantom residuals for every -O0
function, written straight into the backlog this autopsy reads.
R22 clean-fleet: check-all 140 passed, 0 failed of 140; tools-health OK (dedup 1847/0,
C1 234343/234343); 0 NON_MATCHING (G4). Flywheel captured in-session (R30/R31):
cookbook §60, decision-log entry, SETUP.md inventory.
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).
- func_8016CBC0's 137 members were NOT self-decl-blocked (§57 survey: 0 divergent self-decls) but blocked
on the exemplar's 6 LOCAL typedefs (Rec_/Blk_/SVEC_/CLR_/Poly_/Mtx8_8016CBC0). Lifted all 6 verbatim into
src/shared/engine_types.h (fleet-visible via engine_core.h) + removed the locals from the exemplar TU.
No fleet name-collision; exemplar rebuilds byte-identical d19c9580 (the type-lift is byte-neutral).
- family_sweep --hseq --only 0x8016CBC0 --no-preclassify --normalize-self-decls -> 137/137 banked, 0 failed
(the decl-normalize stage a correct no-op here — 0 self-decls). 0 func_8016CBC0 stubs remain fleet-wide.
- R22 clean-fleet 140/140 byte-identical; tools-health OK (dedup 1846/0, C1 234205/234205); 0 NON_MATCHING
linked (G4). fleet 74.9->75.1% instr / 60.1->60.6% distinct / 86.96->87.00% fn-count.
- R14 lesson: two families that both looked like a 'stuck 137-family' needed DIFFERENT levers
(decl-normalize §57 vs type-lift) — route by the real cc1 error, not the shape. session-total +270 members.