mirror of
https://github.com/Druthulu/BFM-decomp
synced 2026-09-27 14:02:04 -04:00
2c4e2344da8afee9c6aeff0939b79b67f5434a38
321 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
2c4e2344da |
fix(phase-28 T5): progress.py — #if 0 blindness + the len()-sum; resident 123/146 -> 122/145
R35: fix the instrument before planting a flag on its denominator.
- #if 0 BLINDNESS: classify() knew `#ifdef NON_MATCHING` (:425) but not `#if 0`, so a dead
analysis body was read as a live definition AND its real INCLUDE_ASM stub counted separately —
the SAME function in BOTH `real` and `stubs`. Live case: resident.c:868-925 wraps a full
void func_800D00E4(s32){...} in #if 0 (its jtbl dossier) and re-declares the stub at :926.
Now the block is skipped entirely: dead code is neither matched nor stubbed.
- THE len()-SUM (the dual defect): `placed` was a set union, so it caught a function in NO bucket
— but `matchable` SUMMED len()s, so a function in TWO buckets counted twice and nothing
complained. matchable/byteident are now SET unions, plus a new OVER-coverage assertion that
fails loudly if any fn lands in multiple buckets. R32 means both directions: nothing missing,
nothing double-counted.
- NEGATIVE CONTROL (the fix must change an answer the old tool gave):
resident REAL 123 -> 122 | matchable 146 -> 145 | 85.62% -> 85.52% | func_800D00E4 no longer
double-counted. FLEET instr 68.9% UNCHANGED (no #if 0 in the overlays) — the fix is scoped.
- FINDING (logged for T7's audit-binaries, does NOT block the flag-plant): the two INDEPENDENT
oracles now agree exactly at 144 — corpus (21 stubs + 123 matched, derived from the tree) and
sig_image (the 2nd oracle) — with EMPTY set difference both ways. progress.py still reports 145
because it counts func_800CEDFC and func_800D33E0, which are DEFINED in resident.c but absent
from sig_image. 0x800CEDFC is the resident's vram base +4 (the first function, code starts at
file offset 0x4 after the leading data word), yet make audit-corpus reports 0 PHANTOM +
0 TRUNCATED. Either sig_image has a boundary blind spot or those defs are not image functions.
progress.py's text-scanning classify() is exactly the re-parsing R33 says should be DERIVED from
corpus instead — a real refactor, logged not rushed.
The flag-plant claim is unaffected: it rests on corpus.stubs('resident') == 21 (tree-derived,
verified 5 ways), not on the contested denominator.
|
||
|
|
fda9eebb42 |
fix(phase-28 T4): wire all 4 SC07 overlays (6174/6457, 95.6%) + REPAIR the registry I destroyed
Completes T4 and corrects two defects I introduced, both landed in commit:0649. - WIRED: 006 1543/1614 · 007 1544/1615 · 010 1544/1614 · 011 1543/1614 = 6174/6457 = 95.6%, ~0 agent tokens. Stubs/overlay ~2400 -> 831/984/898/825. Fleet instr 67.0 -> 68.9%, fn-count 82.16 -> 83.94%. dedup-check 1840 validated / 0 failed; groups now read "138 members [138 binaries]" (was 134); C1 coverage 227211 -> 233385 = exactly +6174. R22 make clean && extract-all && check-all -> 140 passed, 0 failed of 140 at every stage. - FIX #1 — I DESTROYED THE REGISTRY'S DOCUMENTATION, AND EVERY GATE CALLED IT GREEN (H5). The first cut wrote config/dedup.us.yaml with yaml.safe_dump, round-tripping the whole file: 47 comment lines -> 0 (including the curated Phase-11 header explaining WHY the share is source-level) and 1832 `vram: 0x80162FF4` -> `vram: 2148937716` (PyYAML parses YAML-1.1 hex to int; dumps int as decimal). 25,948 lines rewritten. It passed dedup-check 1840/0 AND check-all 140/140 because _addr() accepts both forms: THE DATA WAS CORRECT AND THE DOCUMENT WAS RUINED. Fixed forward (R6, no history rewrite): restored from commit:0649~1 and re-applied the 6174 memberships via a surgical text edit (add_members_surgical). Verified: 1545 insertions / 1545 deletions, 0 non-`binaries:` lines changed, 47 comments + 1908 hex fields intact, and the rebuilt fleet is byte-identical to the destructive version (140/140). THE LESSON: every oracle this project owns measures BYTES, so a formatting-destructive write is invisible to all of them by construction. R34 says the byte-gate is a null COVERAGE oracle; this is the same hole one layer out — it is a null DOCUMENT oracle too. - FIX #2 — I MIS-REPORTED THE DIFFs, TWICE (R14). (a) commit:0649 claims ov_SC07_006's 71 non-banks were "ALL PLUMBING, ZERO DIFF". FALSE — I read head -6 of the classified file and generalized. It has the same 4 DIFFs as the others. (b) I then built the jr guard assuming those 4 were the §53 jr class BECAUSE ov_SC01_077 hosts them in _jr_8017A4AC.c / _jr_80182268.c. has_mid_jr is FALSE for all four (33-52 ins, no jump table): they merely live in a carved jr-REGION split, which sweeps in every function in its address range. HOSTING FILE != FUNCTION CLASS. The guard is KEPT (preventive, §53-correct, currently skips 0 — no jr fn is in the extendable set) with its docstring corrected to record what it is NOT. The 12 DIFFs (0.19%) are UNDIAGNOSED and logged, correctly left as stubs by the gate — not dressed in a story. - The 283 non-banks: 271 PLUMBING (the loose-typing conflict class + the whale, whose body lives in src/shared/func_80144B9C.h so no DEFINE macro exists to expand) + 12 DIFF. Existing tools cover the plumbing (cast_call_sites / canon_sig_reconcile / reconcile_tu). |
||
|
|
c0486fe5f8 |
feat(phase-28 T4): dedup_extend — wire newly-onboarded binaries in; ov_SC07_006 1543/1614 (95.6%)
The 4 SC07 overlays P27 onboarded were byte-clean but NOT citizens: their .c included only
common.h (never ../shared/engine_core.h), so no shared body could reach them, and they
appeared in ZERO dedup groups (1689 groups read "134 binaries", never 138). Each sat at ~80
matched / ~2400 stubs while its siblings were ~2150 matched.
- NEW tools/dedup_extend.py — the missing mode. dedup_propagate is built for CRACK -> AUTHOR
MACRO -> INSTANTIATE: --auto-from scans INLINE DEFS (planned only 11 here; the ~1600 shared
bodies are ALREADY DEFINE_func_* macros in engine_core.h) and --addr dies "no source overlay
has it matched" because no overlay holds an inline def. Extending an existing MACRO-BACKED
group to a newly-onboarded binary is a different operation and nothing implemented it.
- SAFETY (explicit — this feeds the byte-gate): h_exact is the SHA1 of RAW INSTRUCTION BYTES, so
two instances sharing one are identical INCLUDING their jal/lui/%lo reloc immediates — same
callees, same data addresses, same symbols. The body that compiles byte-identically at one
member does so at the other with NO remap. (Exactly why dup_report calls h_exact "guaranteed
byte-match" and h_norm "candidate-only".) A bug here can only FAIL TO BANK, never falsely bank.
- REUSE, DON'T REBUILD (R33): owns only the set computation + the registry edit. The splice and
the gate are harvest_verify verbatim (it already derives each stub's home TU from the corpus
oracle, chunks + bisects, reverts on failure). h_exact members are byte-identical by
construction -> the happy path is ~1 build per binary, not one per function.
- RESULT ov_SC07_006: 1543 / 1614 banked = 95.6%, ~0 agent tokens. Stubs 2374 -> 831.
The 71 non-banks are ALL PLUMBING, ZERO DIFF, in two named classes with existing tools:
* func_80144B9C "undefined reference" — the whale's body lives in src/shared/func_80144B9C.h
(the -O0 shared header), not engine_core.h, so no DEFINE macro exists to expand.
* "conflicting types for D_800A5E60 / func_8012C750 / func_8012C0EC" — the loose-typing
conflict class (cast_call_sites / canon_sig_reconcile / reconcile_tu already exist for it).
- GATES: R22 make clean && extract-all && check-all -> 140 passed, 0 failed of 140, 0 FAIL lines.
dedup-check 1840 validated / 0 failed; groups now read "135 members [135 binaries]" (was 134);
C1 coverage 227211 -> 228754 = exactly +1543. The second oracle accepts the extension.
- Mechanism had been proven by hand first (probe-before-investing): +include + ONE stub ->
DEFINE_func_80128158() -> ov_SC07_006 built 7ca772be BYTE-IDENTICAL, then reverted.
|
||
|
|
4db79a2060 |
feat(phase-28 T1b): the B2 family swept — 102/115 banked (88.7%), fleet 67.0 -> 67.7% instr
The family the roadmap recorded as 0/8 ("~0%, structural families do not template" — the
number that rewrote P29's arithmetic to "(cores cracked) x (reach)") banks at 88.7% when
swept with the carve its own exemplar required. ~0 agent tokens.
- SWEEP: jtbl_family_bank.py over the remaining 107 members ->
{'BANKED': 94, 'gate-fail': 7, 'remap-refuse': 6}. Family total 8 (T1) + 94 = 102/115.
R22: make clean && extract-all && check-all -> 140 passed, 0 failed of 140, 0 FAIL lines.
- FLEET (measured, make report): instr-weighted 67.0 -> 67.7% (+0.7pp, +97,104 ins);
distinct-code 47.8 -> 49.4% (+1.6pp); fn-count 82.16 -> 82.19%. 102 x 952 = 97,104 =
the exact measured instruction delta — the arithmetic reconciles to the byte.
- THE 13-MEMBER TAIL is the predicted shape, and both halves are data for T3:
* 6 remap-refuse = EXACTLY the family's 6 IMM members (cls_counts PURE 109 / IMM 6).
imm_map_tier1 REFUSED rather than guessed: "unresolved immediates: [(512,
'asm-ambiguous')]" — 512 also occurs at a non-differing position, so a blind swap could
corrupt it. This is the concrete shape of T3's IMM stratum.
* 7 gate-fail = genuine byte-DIFFs, correctly rejected. Verified to leave NO residue
(all 7: split_file=none, cfg_refs=0) — no false-bank risk.
- HYGIENE: the 7 "git checkout ... did not match any file" errors are benign (revert of a
never-tracked path). Verified 0 untracked splits belong to a non-banked member; 91 new
splits + 3 banked into existing splits = 94.
- SCOPE (P9, unchanged): still n=1 family, and jr is the rarest class (3/163 matched-exemplar
families). This demonstrates the mechanism at family scale; it does NOT give a rate for the
PURE/IMM mass (98% of the population). T3 measures the swing number.
|
||
|
|
a4640e3a51 |
feat(phase-28 T1): B2 LIVES — 8/8 banked; the "families don't template" doctrine was a missing carve
The roadmap's decisive P28/P29 input (h_seq families bank at ~0%) is byte-refuted. Same
family, same era, through the carve path its own exemplar required: 8 of 8 BANKED.
- THE PROBE: jtbl_family_bank.py func_8017BEBC ov_SC01_000 0x8017bebc --raw
.run/phase26-cracks/func_8017BEBC.c over 8 of 115 members (4 same-address + 4
CROSS-address, exercising to_addr) -> {'BANKED': 8}.
R22: make clean && extract-all && check-all -> 140 passed, 0 failed of 140.
- ROOT CAUSE of the P27 0/8, byte-verified: 0x8017BEBC is a jr/switch core. §47 banked its
exemplar as "lazy isolation -> carve (9-piece interleave) -> splice -> BYTE-IDENTICAL" and
called the fix "×N template-safe". family_sweep.hseq_sweep stages C and gates -- it has NO
CARVE STEP -- so gcc's generated jump table is never placed at the sibling's address. The
entire residual is TWO WORDS: classify_member -> PURE, ndiff=2 @ idx 343/345 =
lui/lw %hi/%lo(jtbl_801EC44C). overlays.mk:112 carves ov_SC01_000_jr_8017BEBC.o for the
exemplar; :134 has no such entry for the member. tools/jtbl_family_bank.py exists to do
exactly this per sibling and had NEVER been run on this family.
- THREE COMPOUNDING FAILURES made the doctrine: (1) wrong tool for the class; (2) n=1 on the
LEAST representative family -- has_mid_jr is 3 of 163 matched-exemplar families (120 of
13,232 members) -- generalized to the whole frontier; (3) its corroborating Phase-26 probes
(tiny-IMM 0/241, PURE 0/134, pinned 0/133) ALL predate _carry_macros (P27 T5, commit:0637).
P27's decision-log calls its own re-probe "a FOURTH phantom exhaustion proof" -- naming the
mechanism that would have faked the first three, and never re-running them. The ~0% doctrine
has NO surviving post-fix evidence.
- SCOPE HONESTY (P9): this refutes the EVIDENCE for ~0%; it does NOT establish a general rate.
n=1, and jr is the rarest class by construction. T3 measures the rate over the population
that actually exists: 1418 matched-exemplar families / 21,889 members (PURE 78% / IMM 20% /
STRUCT 1.8% -- note the roadmap sizes its swing number on STRUCT = 1.8% of the input).
- TWO SELF-CORRECTIONS (R14), both mine: (a) the approved plan's "add jtbl_ to symbol_map" was
a WRONG FIX FROM A TRUE DIAGNOSIS -- a compiler-generated switch table is never named in C,
so there is no token to substitute; the fix is PLACEMENT. No symbol_map change was made and
T1 became a run, not a code change. (b) func_8017BEBC.md's header still says "close=2 of 952"
(pre-§47-slider); the .c was updated, the .md was not -- templating from the header's premise
would have produced zeros indistinguishable from a wall.
- DISTILLED IN-SESSION (R30/R16): cookbook §53 (sweep a family with the tool its exemplar
needed: the carve law, the --raw rule, the symbol_map-jtbl trap, and the "before a 0%
retires a lever" three-question test); calibration.md's decisive table REWRITTEN (the ~0%
row marked an artifact, not a rate; the addressable pool tabulated); decision-log R31.
- Carried: the family's remaining 107 members (~101,864 ins, ~0 agent tokens) -> T1b.
|
||
|
|
76db32455c |
feat(phase-28 T0): fix img_path (derive, don't guess) — the SC07 pool was doubly hidden
R35 sequencing: fix the instrument before the probe that scopes the phase.
- family_remap.img_path: DERIVE the payload from config/splat.<bin>.yaml's target_path
(R33 — the file the BUILD reads, so it cannot drift from the bytes) instead of
reconstructing `.../FILE_{nnn}.dir/0.4.dec` from the alias. RAISES on a missing
payload (R32) — the silent None WAS the defect.
Negative control (the fix must change an answer the old tool gave):
ov_SC01_001 -> 0.4.dec UNCHANGED (no regression)
ov_SC07_006 -> None -> .../1.4.dec
resident -> (n/a) -> MAIN.CD.dir/FILE_010.dir/1.1 (free; feeds T5)
ov_SC99_999 -> None -> raises
Downstream: all 233 shared substantial fns between ov_SC07_006 and ov_SC01_001
classify PURE (reloc-only). Under the old tool every one returned LEN = "not
templatable" AND poisoned its family's diff_class to MIXED (family_hseq.py:141-143).
Same bug class as new_overlay.sh's hardcoded 0.4.dec glob (which hid these four
overlays for a month) — left uncorrected in a second tool. Fourth instance of the
project's dominant defect class, sitting directly under the number P28 must measure.
- .run/family_hseq.json regenerated: 134 -> 138 overlays (the 4 P27 SC07 overlays newly
visible); metrics re-baselined 68.9 -> 67.0% instr (now agreeing with the committed
progress.fleet.md); LEN across the whole frontier = 0 (a phantom-LEN from a missing
image is now structurally impossible). Proven consistent against the post-tools-health
sigs by a second run (byte-identical) rather than assuming sig_image is deterministic.
- FINDING — a large, doubly-hidden target pool: 1255 families / 6268 members / 230,612 ins
whose ONLY unmatched members are in the 4 new SC07 overlays (0 elsewhere — a clean
partition), each behind an ALREADY-MATCHED, byte-proven ov_SC01_077 exemplar. Classes
PURE 5575 (89%) / IMM 633 (10%) / STRUCT 60 (1%). Hidden twice: P27's disc audit created
it by onboarding the overlays but never regenerated the map — and had it, img_path would
have classified every member LEN. Corroborated independently by tools-health: the 4 new
overlays are ~97% unmatched (stubs ~2,400, matched ~80) vs ~85% matched for their
siblings. PREDICTION, not a bank — h_seq predicts, the whole-binary gate decides (G3/P9).
-> T3's headline stratum, and a better probe than planned: the exemplar is already
byte-proven, so a failure isolates the templating mechanism with no drafting variable.
- SELF-CORRECTION (R14): the approved plan's own population figures (163 families /
13,232 members) came from the STALE map — my numbers were an instance of the defect this
phase is about. Honest: 1418 matched-exemplar families / 21,889 unmatched members
(PURE 17,024 = 78% / IMM 4,473 = 20% / STRUCT 392 = 1.8% — the roadmap's "register-drift"
swing class stays ~2% of the input, so that framing is unchanged). Legacy pool unchanged
at 163 families (the fix + the 4 overlays are purely additive).
- T3 strata (honest): SC07-only 1255 fam / 6268 mem / 230,612 ins · legacy PURE non-jr
95 / 7993 / 478,379 · legacy IMM 36 / 6644 / 212,707 · legacy MIXED 30 / 968 / 10,462 ·
legacy PURE w/ jr 2 / 16 / 5,088. Total addressable 937,248 ins = 21.7% of all remaining
weight = 7.16pp of fleet instr if it all banked — the prize the roadmap declared dead.
- tools-health GREEN: sigs fresh; corpus(+resident) 0 PHANTOM + 0 TRUNCATED; cdecl;
report(lint + dedup 1840 validated / 0 failed, C1 coverage 227211/227211). No source or
build input touched (analysis tooling + regenerated digests only) -> no byte claim, no
R22 cycle owed. docs/duplicates.cross.md regenerated: overlays 134x -> 138x, h_exact
cross-binary 9366 -> 9484 groups; resident sig now the sig_image one (P27 T10 intent).
|
||
|
|
d1ef983af0 |
docs(phase-27 T1 close): func_80176734 crack + distill — the CSE address-fold antidote
The last Fable5 pass of the sprint (Drew capped further waves at 86% context). func_80176734 (371 ins, fresh un-drafted core): NO bank (mine=370 vs 371, 5 permuter-shaped clusters — entry-schedule tie, caller-saved shuffles, a combine-merge missing insn, qty ties), pin-free, honestly handed off (P9; match_one confirms the DIFF). Draft -> decomp-permuter warm-start (P29). Idiom harvest (cookbook cse_expr §H): - THE CSE ADDRESS-FOLD ANTIDOTE (zero asm): find_best_addr's cost-ungated qty-const fold + from_plus re-association eat reg-based global accesses on every cse walk; a balanced if/else DIAMOND makes the merge label barrier-preceded -> fresh cse table -> both folds die with no #APP. Replaced two asm dials. - update_equiv_regs doubles live_length for single-set REG_EQUIV pseudos (local-alloc.c:1064) — a 2nd set forfeits the doubling, ~4x the allocno priority; explains a "my dial broke the $s-order" class. - record_jump_equiv fall-through delete (cse.c:7511) — a recognition tell for genuine dead source logic. T1 sprint COMPLETE: 4 cracks + the SIGABRT characterization, 0 direct banks, but 3 wall reclassifications + 2 cracked roots + the pin-crash wall dissolved + ~9 new pin-free levers. Fable5 DISCOVERS, cheap-Opus APPLIES — the ROI is idioms, not banks (docs/calibration.md). |
||
|
|
ce88baf365 |
feat(phase-27 T9): calibration — the templatability swing measured (structural families are NOT cheap)
docs/calibration.md — the byte-gate-grounded rates that size P28/P29 (roadmap §6 held yield projections until this). - VELOCITY: instr 68.9->67.0% (a T7 denominator re-baselining DOWN, not a regression) + ~0 matches banked (an infrastructure/findings phase). The honest flip-checkpoint read: denominator correction + unblocking findings, NOT 0 progress/session — velocity resumes at P29, re-measure there. - THE TEMPLATABILITY SWING (decisive for P28/P29): h_exact reach-N cores propagate ~xN near-100% (§52: 5 cores -> 670 instances) vs h_seq/h_norm structural families ~0% (0x8017BEBC: 106/112 stage but 0/8 bank, all genuine DIFF). So remaining yield = per-member cracking + mechanical xN for the h_exact cores, NOT "template x120 the 986 families" — B1/B2's cheap-harvest hope is byte-refuted. The 223-stub frontier: 101 reach-134 (xN-able if cracked) + 119 reach-1. - COST/TIER: Fable5 ~230k tok/fn, 0 banks / 5 — ROI is idioms + the pin-crash wall dissolved, not banks (the doctrine held). cheap-Opus is the banking tier; permuter tail exhausted; local-v3 $0/<=15. - HONEST GAP: the headline member-adapt close-rate on register-drift members needs P28's member_adapt tool (chicken-and-egg) -> P28 opens by measuring it on a byte-gated sample, per the risk register. - NEW un-projected fuel: ~20 PINS-class stubs now harvestable (pin-crash dissolved, T5). |
||
|
|
0f68a83cfa |
feat(phase-27 T8): worklist --assert-partition (R32) + honest re-scan + ledger corruption fixed
- worklist --assert-partition: the audit's literal R32 prescription (tooling-audit.md:1173) — enumerate live stubs from corpus.stubs (the invariant, R33), assert the fuel manifest partitions its source overlay's stubs, exactly one row each. Scoped honestly (worklist's universe is ONE overlay ~223 stubs, not the fleet's 53k — a fleet partition is a scope change, not a flag). PROVEN: it caught 5 stale rows (pin-free cores Phase-26 banked, manifest never re-derived) -> FAIL exit 1. - honest re-scan: build_fuel_manifest on the fixed tools + 140 binaries. Giants re-verified reach-138 (was 134 — the SC07 overlays now counted). Partition PASSES 223==223 after refresh. - ledger corruption fixed: func_80178004's 2 false `close=0 "MATCH"` records (a Phase-26-retracted myth — the seed's best was 5 pinned, and a real close=0 whole-binary match BANKS; it is still a stub) -> corrected to the honest close=91 regalloc wall. func_8012E364 already honest (close=23 — the "stale closeness" flag was itself stale). No real duplicate rows (load_best dedups by addr; the uniq hits were func names in where_stuck prose). docs/worklist.md + docs/backlog.md regenerated. - the 1,670-untriaged near-miss triage SCOPED TO P29 (P5d): Phase-21 automation leftovers whose class labels re-derive at harvest, and the pin-crash finding re-buckets the PINS class — an Ultracode fan-out buys low-durable labels; the gate's residue map is the partition + the class summary, done. |
||
|
|
54bdf96218 |
docs(phase-27 T1): distill the Fable5 wave — the pin-crash wall refuted + 3 RC-6 downgrades
The flywheel step (R16/R30): turn the wave-1 + SIGABRT byte-proven findings into cookbook/codegen-map knowledge, in the producing session. The distillation REWRITES wall verdicts, so accuracy is load-bearing. - cookbook §42e-CORRECTION: the "pin-crash wall" (register-pin-heavy families "SIGABRT the sibling TU, ov077-TU-context-specific, NOT ×134-recoverable") is REFUTED. The SIGABRT is real (sched.c:2725 create_reg_dead_note, a sched1 REG_DEAD-note conservation bug) but was TRIGGERED by extract_unit dropping file-scope #define macros (the T5 bug) -> implicit-call GTE ops -> caller-saved pins in the fatal shape. Only 1 of 4 families genuinely crashed; 3 were exit-33 plumbing folded into one crash bucket. Fixed, all 4 stage 133/133 clean. Per-pin predicate recorded. P31's pin route is OPEN. - cookbook §44-Lever-5: the 3 functions it cited as intrinsic (func_8014D820/8016CBC0/801670E4) are each oracle-refuted (2 cracked roots + 1 RC-6-not-S3). Corrected the "NEVER ship pinned, it SIGABRTs" claim per §42e-CORRECTION. - gcc-2.7.2-map/regalloc.md §H: THE reg_renumber-swap oracle (discriminate RC-6 allocation from S3 scheduling in one gdb run — patch reg_renumber at reload entry, swap the contested regs; byte-exact = pure allocation), RC-14 reused-load-temp serialization (the MERGE pole; pin-free, cheap-Opus), RC-15 the density dial across a floor_log2 boundary (subsumes "coalescing knife-edge"), and the local-vs- global allocation tie as a precisely-named honest sub-class. Continues the §F/§G RC-6-downgrade series. - decision-log.md R31: the 3 Phase-27 strategic findings (disc is bigger: 140 + 39 modules; a wall was our tool again; a cheap win is dead) + the through-line — the roadmap's numbers were red-teamed, the tools under them were not, until this phase. func_80176734 (fresh-core wave-2 agent) still running; its findings fold in before the PhaseEnd. |
||
|
|
427baba3bf |
feat(phase-27 T10): completion dashboard (main in the weighted metric) + the resident second oracle
The metrics contract (roadmap §1) wants all three metrics WITH main in the denominators, and the
second, independent boundary oracle (R34) extended beyond the overlays. Both had landmines.
10a — main into the weighted metric, safely:
- weighted_metrics off the func_-only src_stubs regex onto corpus.stubs (R33). THE LANDMINE IS
REAL: src_stubs("SLUS_007.26") globs src/SLUS_007.26/*.c -> 0 files -> every row "matched" ->
main 100% + fleet % silently inflates. Routing through corpus.stubs is a PROVEN 0.000pp no-op on
the existing fleet (overlays are all func_) and closes the curated-name leak.
- a SEPARATE "MAIN game-code weighted" line (0.7%): main's Ghidra sig excludes the LINKED PsyQ
objects (Ghidra never analysed them), which is exactly right for a game-code metric (LINKED is
complete, counted in fn-count). Reported un-folded and caveated (month-stale sig, PROVISIONAL) —
folding a stale/incomplete value into the decomp.dev headline would mislead the flip checkpoint.
10b — the resident second oracle:
- make sig-resident: sig_image on the resident flat blob (byte-derived, not Ghidra). corpus.
sig_is_independent now covers resident -> audit-corpus checks its boundaries too. Probed clean
BEFORE wiring (144 fns, all 21 stubs present, 0 phantom), verified 0 phantom + 0 truncated.
- sig-overlays now derives its payload list from config/overlays.mk, not a 0.4.dec glob that
silently dropped the 4 SC07 index-1 overlays (the audit's own silent-skip class). tools-health
regenerates sig-overlays + sig-resident first so the audit never crashes on an absent sig.
10c — main's second oracle: docs/second-oracle.md. sig_image can't sign the PS-X EXE yet (0x800
header offset, interleaved data/linked islands, one text range); seeding from splat would destroy
independence for the PHANTOM class specifically. Honest deferral + scoped design, not a fake oracle.
- docs/progress.fleet.md regenerated: 140 binaries · fn-count 82.16% · instr-weighted 67.0%
(the honest post-T7 drop from 68.9%) · distinct 47.8% · MAIN game-code 0.7% (separate).
- SETUP §6.3 updated (R21).
|
||
|
|
264fe6c115 |
feat(phase-27 T7): disc-completeness audit — onboard 4 hidden SC07 overlays (136->140) + the type sweep
The whole-binary byte-gate is structurally blind to code nobody onboarded (R34): check-all is
green over the onboarded set no matter what code sits unbuilt on the disc. This reconciles the
onboarded set against every code-bearing PAC payload.
- new_overlay.sh: optional [ENTRY] arg (default 0.4) reaches a non-0.4.dec payload. Onboarded
ov_SC07_{006,007,010,011} from 1.4.dec (they put graphics at PAC entry 0, the code overlay at
entry 1 — invisible to the 0.4 hardcode for a month). Each byte-identical (7ca772be / b3b95547 /
d7b5875d / 9885af74). FLEET 136 -> 140; check-all 140/140 (T2's pass==N re-baselined cleanly).
difficulty.py NOT in the insertion set anymore (it derives, T6) -> only 3 tool dicts touched.
- tools/disc_code_sweep.py: decode every payload (reusing sig_image.make_insn) and gate code on
BOTH valid>=0.90 AND jr_$ra density>=0.01. The jr_$ra gate is decisive: isValid() alone flags
389 false hits (type-0/2 structured data decodes ~100% valid but has ZERO returns); jr_$ra
separates code (~2.9-3.4%) from data (0.000%), validated on positive+negative controls.
- FINDING (docs/disc-completeness.md): type-4 location overlays are COMPLETE (138/138). All other
types are data EXCEPT type-1 = 40 code payloads, 1 onboarded (the resident), 39 HIDDEN
resident-class modules (mostly MAIN.CD/FILE_XXX/1.1). They load at UNKNOWN addresses (not the
shared overlay slot), so they are NOT mechanically onboardable — byte-verifying a build binary
needs its load address (P9), knowable only by runtime RE (the Phase-3 method). Deferred with
evidence, NOT force-onboarded at a guess.
- CONSEQUENCE: game-code TRUE 100% now spans 140 onboarded binaries PLUS ~39 type-1 modules
pending load-address RE. The roadmap assumed 136 — this is a real re-baselining (the +4 overlays
also add ~2.45 MB to the denominator; every family propagation is now x138). Flows to T10/T11.
- SETUP §6.3 tool inventory updated (R21).
|
||
|
|
e0a0becfaa |
feat(phase-27 T4): one cdecl typedef-strip primitive (was six regexes) + surface cc1 stderr
The plan named two defective regexes; the tree had SIX with complementary holes, each silently recording the resulting compile failure as "not a match" — a plumbing error wearing a compiler wall's clothes, the exact class the 26-A audit exists to end (R32). - cdecl.py: the canonical primitive — typedef_names(tu_path) + strip_provided_typedefs (draft, provided). Built on tu_statements (robust) NOT tu_scope (which coverage-asserts -> would crash the byte-gate on any unrelated unparseable file-scope statement). Splits multi-typedef lines (split_statements, depth-aware); covers scalar AND struct typedefs; keeps draft-local types. lru_cached. - harvest_verify.py: strips PER-TU (cdecl.typedef_names of the draft's real target TU) -> unblocks the 39 struct-typedef drafts the scalar-only _TD dropped. And SURFACES cc1 stderr: build() stashes it; a single-draft failure is classified DIFF / PLUMBING:… / CC1-FAIL / SKIP -> .run/harvest_failed.classified.txt. A `redefinition` is no longer recorded byte-identically to a codegen miss. - masked_diff.py: strip_scalar_typedefs() (common.h set derived from the header once, R33, cached) replaces SCALAR_TYPEDEF_RE.sub for the ISOLATED compile; wired into match_one + p16_permute. Fixes the multi-typedef-LINE skip that discarded 42 masked-MATCH drafts over whitespace. Unblocks B4's func_8015C32C (redefinition of 's16'). - canon_sig_reconcile / eval_lora / format_finetune keep their own copies — migrate per-bank, byte-gated (the audit-prescribed cadence, not a big-bang swap). VERIFIED: - HEADLINE known-answer: func_8015C030 -> MATCH (23 ins) UNEDITED via match_one (was CC1-FAIL; the multi-line typedef split alone fixes it — a live x134-family draft that was being discarded over whitespace). - unit: 7/7 scalars stripped; a local struct KEPT; a TU-provided Blk16 stripped. - classifier unit: DIFF / PLUMBING:… / CC1-FAIL / SKIP all label correctly. - all 5 edited tools import + AST-parse clean. - R22 clean-fleet: check-all 136/136; main clean-rebuild 143dbb89. (A mid-test c4546248 "mismatch" was a stale-incremental artifact from concurrent compiles, cleared by a clean rebuild — the R22 lesson; edits touch only tools/, src/ stayed git-clean.) - SAFETY: a strip bug can only fail-to-bank, never falsely bank (INCLUDE_ASM pastes the original asm; a wrong draft always changes bytes -> always fails SHA1). |
||
|
|
ebdef9012b |
feat(phase-27 T2): make the Makefile fail-closed — the enabling fix for every downstream gate
The roadmap §5 asserted `make report` is fail-closed. It was NOT: .ONESHELL sends each whole recipe to one `bash -c`, so with no -e only the LAST command's exit survives and every earlier failure is swallowed. `dedup-check` "gated" purely by being last; lint_symbol_refs / progress --audit / difficulty / dup_report were non-gates. That is the 26-A audit's own thesis (a loud failure nobody counts is as invisible as a silent one) biting the audit's infrastructure — and until it's fixed, any R32 assertion added to a report-invoked tool is swallowed on arrival. - .SHELLFLAGS := -ec (global fail-closed). ONE documented opt-out: check-env (set +e — its contract is accumulate-every-failure-and-report, which -e would truncate at the first missing tool). - check-all:610 grep -c landmine fixed (|| true): grep -c exits 1 on zero matches, which -e treats as fatal in a command substitution -> check-all would FAIL exactly when nothing did. - check-all / extract-all: assert COVERAGE (pass == N), not the absence of a failure marker. The old `fail == 0` / `! grep -q` form was a VACUOUS PASS on an empty pipeline (R32). - new `make tools-health` = audit-corpus + audit-cdecl + report, fail-closed — the deliberate pre-matching ritual the roadmap's standing invariant names, and the dependent the two derived oracles never had (nothing invoked them). NOT a report/build prereq — audit-cdecl cross-compiles every C decl through gcc (~minutes). SETUP §6.3 documents it (R21). VERIFIED: - NEGATIVE CONTROL (the proof): a broken lint_symbol_refs makes `make report` exit 0 under the old .SHELLFLAGS=-c and exit 2 under -ec. The swallow was real, not theoretical. - the grep -c landmine + the vacuous-pass both reproduced and fixed in isolation. - check-env still exits 0 (the opt-out works); recipe sweep found the Makefile already -e-aware (set -o pipefail, explicit || true) — line 610 was the only real hazard. - R22 clean-fleet: make check-all -> 136/136 byte-identical; a forced main re-extract+rebuild drove the full splat->cpp->cc1->maspsx->as->ld->objcopy->check pipeline under -e -> 143dbb89. - audit-corpus 7s / audit-cdecl green / tools-health wired. |
||
|
|
6344a2c424 |
docs(roadmap): adopt the Road-to-100 endgame roadmap (Phase 27+) — supersedes the family-endgame megaplan
- docs/roadmap-to-100.md: the adopted P27-P32 roadmap to game-code TRUE 100% + public flip + Gen2 exit. Contract (Drew 2026-07-15): true 100% (walls re-attacked until they fall), PsyQ LINKED = complete (libs-from-source = far-future note), flip AT 100% (standing per-phase velocity checkpoint keeps the timing falsifiable), Fable5 window ~7/19 (P27 discovery sprint runs FIRST). Measured baseline from committed post-audit artifacts only; residue buckets B1-B12 incl. the never-probed 0x8017BEBC IMM family (~106k ins) and the main/resident second-oracle gap; foreseen-tooling table (member_adapt, gate farm, fleet Ghidra-C prefetch, diff_regions, cc1_probe, assert-partition); authority rules (docs-layer advisory; every PhaseEnd carries a 'Roadmap delta' line; constitution + latest PhaseEnd win) - docs/decision-log.md (R31): the adoption entry — Drew's four contract decisions, the flip-timing tension + checkpoint, the 16-defect red-team pass that purged numbers carried past their invalidation events (R14 at planning scale) - docs/family-endgame-megaplan.md: SUPERSEDED banner (content preserved; h_seq reframe survives, the templating thesis is byte-proven spent per PhaseEnd_Phase26) - memory: roadmap-to-100 pointer added; structural-family-mechanical-remap corrected with the Phase-26 probe results (outside the repo tree) - Phase 27 NOT started (fresh session, plan mode, per the constitution) |
||
|
|
1bbab78c65 |
feat(phase-26): close — family engine + the tooling-integrity audit + the §52 discovery-flywheel; mechanical harvest byte-proven exhausted; fleet 58.2->68.9% instr (v1.25.0)
- FAMILY ENGINE (Tasks 1-6): family_remap (extended reloc tracker + single-pass subst) + family_hseq (the h_seq reframe) + family_sweep (crack-one -> template-x134 -> byte-gate) + canon_sig_reconcile v3.2 + rtu_match. Sessions 6-8 cracked 13 cores (58.2->66.5% instr). - 26-A TOOLING-INTEGRITY AUDIT (inserted half-phase, A0-A11): the tools WERE several of the walls. Fixed ~15; DELETED decaying scanners (R33); built corpus.py + cdecl.py (derived, coverage-asserted oracles) + make audit-corpus (a SECOND, disagreeing oracle, R34); the listCdBuffer 193-slice corpus defect -> 0; masked_diff 150 closeness-lies -> 4; the stale- object false-pass closed. Payoff 66.5->68.6% instr. docs/tooling-audit.md AUDIT-CLOSE LEDGER. - 52 DISCOVERY-FLYWHEEL (Task 7): single Fable5 on func_80178004 = intrinsic 3-integer regalloc wall, BUT distilled the walker-family idiom (52); two cheap-Opus waves applied it -> 5 pin-free cores banked x134 = 670 instances (68.6->68.9%). 4 named wall classes; 52/52a/52b. pin-guard comment false-positive fixed; family_sweep --allow-pins. - FINDING (R14/P9, 3 probes 0%): the matched-sib mechanical harvest is EXHAUSTED; the manifest's ~13k "templatable" members are an h_seq prediction the byte-gate refuses. Phase-26's templating thesis is spent -> close, open Phase 27 with byte-gate-honest re-scans. - R22 clean-fleet 136/136 BYTE-IDENTICAL throughout; dedup 1840/0; 0 NON_MATCHING (G4). - rules R32 (coverage assertion) / R33 (derive, don't re-derive) / R34 (a second, disagreeing oracle). worklog -> phase-ends/logs/Phase26.md (R19). bumps 1.24.0 -> 1.25.0. |
||
|
|
d40711fe5f |
chore(phase-26 T7): family_sweep --allow-pins flag + honest matched-sib finding
- family_sweep: --allow-pins bypasses the §42e pinned-exemplar skip (template WITH pins, byte-gate arbitrates) — added to TEST the func_8017A4AC pinned-×134 precedent. - FINDING (3 probes, all 0% banked): the matched-sib harvest is TAPPED. tiny-IMM 0/241, PURE reach-134 0/134, pinned-PURE-with-pins 0/133. The manifest's ~13,075 'templatable' member-slots are an over-prediction the whole-binary byte-gate refuses (collision/drift/ pin-crash). A3h + the wave propagations already banked everything cleanly templatable. - regenerated family-hseq.md. |
||
|
|
ed09ee749f |
feat(phase-26 T7): §52 sibling wave 2 — 3 more cores banked ×134 (402 instances)
Second cheap-Opus §52 wave over the close=0 regalloc cluster (armed with §52a):
- BANKED ×134: func_801379FC (97), func_801497A8 (47), func_801495C4 (34) —
3 exemplars + 399 members = 402 function-instances, 0 gate failures.
- 2 whole-binary-near (func_8012E138, func_8012F40C — match_one MATCH, A10 gap),
1 new wall (func_8012B4B8 — symbol-address-base wins-low-needs-high, a 3rd class).
- §52b: new verified de-pin levers (per-loop pseudos for register role-swap; the
RC-7 second-set dial to defeat rematerialization; value-barriers dissolve the
CSE-stack-address-common wall) + the new wall class + the match_one→whole-binary
gap-at-scale finding.
- TOOL FIX: family_sweep §42e pin-guard was a FALSE POSITIVE — it matched
'__asm__("$N")' inside COMMENTS that document a REMOVED pin (recovered
func_801495C4's 133 members). Now strips comments before the pin check.
- R22 clean-fleet 136/136 BYTE-IDENTICAL; dedup 1840/0.
- Wave 1+2 combined: 5 pin-free cracks -> 670 instances, from the walled flagship's idiom.
|
||
|
|
06e43873e9 |
feat(phase-26 T7): §52 regalloc sibling wave — 2 cores banked ×134 (268 instances)
The Fable5 walker-family idiom (§52, from the func_80178004 wall) applied by a 6-agent cheap-Opus wave over the regalloc-order reach-134 cluster: - BANKED ×134: func_80171FFC (40 ins), func_801775E0 (67 ins) — 2 exemplars + 266 members = 268 function-instances, 0 gate failures (family_sweep byte-gate). - 4 precisely-characterized walls (P9), each yielding a byte-verified lever: func_80167714 (whole-binary near), func_80177AD4 (non-coalescing delay-slot copy), func_80169228 (NEW caller-saved priority-first-fit wall), func_80131A34 (save-order/ load-hoist tension; new const-unchanging-load lever). - §52a: the wave's new banking levers (pass-real-args/RC-10, store-base-both-arms, copy-chain-direction, pp-decl-schedule, const-unchanging-load/RC-3) + the two new intrinsic-wall classes. Fable5 DISCOVERS, cheap-Opus APPLIES. - fn-count 84.27→84.35% (+268), instr-weighted 68.6→68.7% (+14,338 ins), distinct +2. - R22 clean-fleet 136/136 BYTE-IDENTICAL; dedup 1840/0. |
||
|
|
8f3e4a12ba |
docs(phase-26): T7 re-baseline + §52 walker-family regalloc idiom (func_80178004 wall)
- re-baseline the target frontier from the fixed tools (R14): 228 ov077 stubs (broken manifest saw 30); worklist/family-hseq regenerated. 68.6% instr / 49.2% distinct. - R14 corrections to the audit handoff: the '~1,200 type-heavy' was already banked by A3h (+2,675); the real remaining lever is 128 matched-sib families (~2.64M templ ins), and register pins are NOT a banking blocker (func_8017A4AC banked ×134 with pins). - Task 7 is near-miss CLOSING (close 1-5 re-gate = 0/13 through the fixed pipeline), not fresh crack. - §52: single Fable5 on func_80178004 (regalloc-order class exemplar) = honest wall (P9), structure-exact 163/165, residual = 3 compiler-internal register-alloc integers, likely intrinsic; byte-verified 126/165. Correction: the 'pinned MATCH' was a myth (never matched). 6 byte-proven walker-family levers + the skeleton idiom transfer to the 11 regalloc-order siblings (Fable5 discovers, cheap-Opus applies). decision-log entry (R31). |
||
|
|
a33c6f85f5 |
docs(phase-26a): A11 — distill + close the tooling-integrity audit (26-A COMPLETE)
Closed the inserted half-phase. tooling-audit.md: DIAGNOSIS -> AUDIT-CLOSE LEDGER (A1-A10 outcomes + the payoff 66.5->68.6% instr + remaining/handoff); the "two rules" -> R32/R33/R34 crisp for P10 ratification at the Phase-26 PhaseEnd. decision-log: the A10 wall-re-test verdict (R31 -- the broken tools WERE the walls; the payoff was banked by the fixes; the closeness-0 residual is genuine; the real deliverable is the 3 rules + the derived-oracle pattern). SETUP: the A9d-A10 tool changes (R21). Cookbook §51 verified complete; LAW 3 tagged R34. Observables green: final R22 clean-fleet 136/136 BYTE-IDENTICAL; make report EXIT 0 (dedup 1840/0, C1 227211/227211 signed, lint_symbol_refs wired + passing); audit-corpus 0 slices; audit-cdecl green. Zero src/config changes this session. Phase 26 resumes at Task 7 (fresh session). |
||
|
|
b1c58d7668 |
docs(phase-26a): A10 wave 1 — closeness-0 wall re-test CONFIRMED REAL (0/958 bank)
Re-gated all 958 closeness-0 open-stub backlog drafts through the FIXED gate across 135 binaries in parallel: banked=0, near=957, failed=71. The closeness-0 backlog is genuine whole-binary near-misses, NOT tooling misses -- match_one's isolated closeness==0 systematically overstates whole-binary bankability, and the repaired gate recovers none. P9: a re-confirmed wall is as valuable as a dissolved one. (The audit's tooling-walls were already banked by A3f/g/h + A9b, +2.1% instr.) backlog.py: env-gated BACKLOG_NO_RENDER so parallel workers skip the render race (append is atomic) -- backward-compatible parallel-safety. backlog.md refreshed with the re-test's whole-binary-informed scores. |
||
|
|
ea20bdf9f3 |
fix(phase-26a): A9g — jr_inventory: retire the ephemeral roster, derive banked from the image (R33)
jr_inventory's `banked` set was filtered by an EPHEMERAL, gitignored .run/banked_func_*.json roster: a `rm -rf .run` / fresh clone would blind ALL banked jr at once, cross-address siblings (roster named after the exemplar) were structurally invisible, and non-leader banked jr were missed. "The purest R33 case in the group" (audit). FIX (the audit's exact prescription): delete the roster glob + `cand` filter; `banked` is DERIVED FROM THE IMAGE — a real-C def/define fn is a banked jr iff family_remap.reloc_targets shows it references a committed .rodata carve offset (config + image, both durable; cross-address- and non-leader-immune). R32 assertion: every committed carve must resolve to EXACTLY ONE owner or abort (a stranded/duplicated carve is the §8b func_801734BC incident, never silent). Also fixed the adjacent finding: the asm_jr scan's func_-fullmatch dropped the curated-name listCdBuffer jr; now resolved via oss.addr_of(). (The --only path's own fullmatch is left — it parses user input, not the corpus.) Perf: read the overlay image ONCE and pass it to reloc_targets(..., data=) — a new backward-compatible param on family_remap (regression: 0/80 mismatch vs the re-read path). Verified: data-param behavior-identical; the R33 win — ov_SC02_000 now finds the cross-address sibling func_8017FCB0 the roster missed; full-fleet parallel run = 134/134 OK, 0 false aborts, 1336 banked jr == 1336 carves -> 1:1 ownership holds fleet-wide. Byte-safe: jr_isolate_all is not in the make build/extract path (R22-neutral); the change makes future isolations strictly more correct. |
||
|
|
96e025a324 |
fix(phase-26a): A9f — overlay_src_split swallowed 2 real definitions; the selftest was blind
scan_construct's force_decl latched from the FIRST token and returned at the
first depth-0 `;`, so a definition sharing a physical line with leading externs
(`extern A; extern B; void f(){...}`) was never anchored — absorbed into the
next anchor's preamble. The parser jr_isolate_all rewrites source from was short
two functions in the exemplar overlay. The round-trip selftest is a SERIALISATION
check (a miss lands in a preamble -> round-trip still exact BY CONSTRUCTION), so
it was structurally incapable of seeing this.
FIX (byte-safe): force_decl no longer survives a same-line `;` with trailing
code — re-classify from the remainder and keep scanning so the def anchors (its
leading externs stay in its whole-line item text -> round-trip byte-identical).
Rejected the audit's "split into 3 constructs": round-trip joins whole-line
chunks with `\n`, so sub-line splitting would insert a newline where a space was.
def_name now names the LAST top-level header before `{` (the definition, not the
first same-line extern; byte-identical on every single-def construct).
R32: hidden_definitions() coverage oracle wired into selftest — an independent
detector of `func_XXXX(...){` bodies not anchored. The selftest is now a coverage
check, not just serialisation.
Verified: 2 swallowed -> 0; regression over 1738 overlay .c = 0 round-trip fails,
0 non-monotonic, 0 non-additive changes, +2 anchored defs. Byte-safe: tool not in
the build path (R22-neutral); ov_SC01_077 rebuilds d19c9580; neither def straddles
a committed subseg boundary. Audit ledger line refs were stale (src rewritten);
real cases are ov_SC01_077_after.c:2020 + ov_SC01_077_jr_8015444C.c:1495.
|
||
|
|
40477281ce |
fix(phase-26a): A9d — retire the dead Phase-17 canonical-sig chain (R33)
DELETE tools/census_conflict_callees.py + tools/derive_canonical_sigs.py. - census_conflict_callees: audit-CONFIRMED marked-for-deletion (commit:0593; decision-log 836). It re-derives from C text the per-TU "defined/declared/ stubbed/external?" question that reconcile_tu (Phase 26) answers FROM THE BUILD — and does it WRONG in the unsafe direction (unknown -> conflict-free). - derive_canonical_sigs (census's ONLY consumer): genuinely dead — last touched Phase-17 (commit:0140), output .run/canonical_sigs.json read by nothing (no Makefile/workflow/import), no-ops on the 2-byte [] input, asm-arity heuristic 36% wrong vs byte-exact banked C. Its purpose was retired in A3d (fleet-majority oracle -> reconcile_tu's per-TU oracle). Deleting census orphans it, so the whole dead chain ceases to exist (R33: the best outcome is a DELETED SCANNER, not a fixed regex). Byte-neutral by construction (neither tool is in any build/report path): module-import smoke over the 13 importable harvest/bank/report/reconcile tools = all clean; bank_exemplar is a run-only script (indexes sys.argv at module scope), imports neither deleted module. No src/config change -> no byte moves. Doc-pointer hygiene: hand-matching-process.md 8a, matching-cookbook.md (canonical-sig-layer entry), tooling-audit.md (ledger row + derive entry) all annotated DELETED/historical so nothing points at a nonexistent tool. |
||
|
|
3509acf4b7 |
feat(phase-26a): A9b — func_8017A4AC banked ×134 (536-ins giant, wall re-test payoff)
The A10 re-test payoff. func_8017A4AC (536 ins, reach-134) — "blocked on plumbing" since session 8 — banks now that the audit repaired the recover path (A3d reconcile_tu / A3e gate). jtbl_family_bank --raw swept all 133 siblings (per-sibling isolate → jtbl carve → remap_hseq + canon_sig_reconcile → whole-binary gate): 133/133 BANKED, 0 failed. 0 still-stub overlays. R22 CLEAN-FLEET (make clean + extract-all + check-all): 136 passed, 0 failed of 136. dedup-check 1840/0 (jtbl sweep banks are per-overlay src, not registry). DELTA: instr-weighted 68.1% -> 68.6% (+0.5%, ~71,824 shipped .text instructions) distinct-code 48.0% -> 49.2% (+1.2% — the siblings are per-location byte-variants) The audit thesis, demonstrated: a giant "wall" that stood for many phases was our TOOLING (the recover path could not resolve its struct/fn-ptr conflicts), not an intrinsic compiler residual. Once the oracle was fixed, the wall dissolved and banked ×134. |
||
|
|
6139800e6d |
feat(phase-26a): A3h — family_sweep --hseq re-harvest, +2,675 member banks (post-audit-fix)
Re-ran the mechanical h_seq family sweep after the audit tool-fixes (A3–A8) + the 14 new
Bucket-P exemplars regenerated the manifest. family_sweep --hseq --band all templated each
matched exemplar's still-stubbed members per sibling (reloc/immediate remap) and byte-gated:
BANKED 2,675 member-matches / 9,698 failed (22% — the hard residual; the easy bands were
harvested in earlier sessions, so what's left fails the whole-binary gate on jtbl / type /
plumbing, correctly rejected by G3/P9). Skipped: 3,319 pinned-exemplar (×1-only, cc1-crash
siblings, §42e), 212 unresolved-immediates, 137 STRUCT.
223 families with a matched ov077 exemplar contributed. R22 CLEAN-FLEET (make clean +
extract-all + check-all): 136 passed, 0 failed of 136. dedup-check 1840/0 (unchanged — hseq
banks are per-overlay src, not registry).
DELTA:
instr-weighted 67.4% -> 68.1% (+0.7%)
distinct-code 46.8% -> 48.0% (+1.2%, +1,435 unique fns — templated members are distinct
byte-variants, so this moves BOTH metrics unlike propagation)
876 overlay .c files + progress.fleet.md + family-hseq.md
Only 33 of the 567 substantial frontier families have a matched exemplar — the rest need
CRACKING (Phase-26 Task 7, Fable5). Remaining standing lead: Bucket X (~905 absent-from-ov077
byte-exact drafts) via per-overlay gate — next.
|
||
|
|
2f38e31e76 |
feat(phase-26a): A3h — propagate 14 fleet-wide byte-exact stubs ×134 (Bucket P)
The standing-lead harvest (A3f/A3g continuation), measured precisely first (R14). Of the
~1,060 still-open byte-exact functions in the backlog:
- Bucket G (67 open in ov_SC01_077): re-gated through the A3e-fixed gate_stage
--no-propagate -> 0 banked. HONEST: A3f already took the bankable 33; the residual is
the known hard classes (jtbl-rodata / register-pins / struct-collision) + stale backlog
rows whose LATEST state is a WAVE mismatch. Correct G3/P9 rejection.
- Bucket P (88 matched in ov077, open in siblings): the clean lead. dedup_propagate --addr
(A3g primitive) skipped 70 as h_exact reach<2 (per-location byte VARIANTS -> family_sweep
territory, not plain propagation) and propagated the 14 genuine PURE fleet families:
5 top (func_80129C40/8012A6D0/80130A18/80131D68/80136DFC) + 9 more; 2 stragglers
dropped all-or-nothing (0x80173A60, 0x8014C568 -> --recover candidates).
Each propagated x~133 (dedup_propagate internal gate: 134 overlays byte-identical).
R22 CLEAN-FLEET (make clean + extract-all + check-all): 136 passed, 0 failed of 136.
dedup-check: 1826 -> 1840 validated, 0 failed | C1 227211/227211.
DELTA:
instr-weighted 66.8% -> 67.4% (+~1,862 member instantiations shipped from C)
distinct-code 46.8% -> 46.8% (flat: propagation adds MEMBERS, not new distinct code)
673 files (671 overlay .c instantiations + engine_core.h) + dedup.us.yaml + progress.fleet.md
Remaining standing lead: the ~72 variant Bucket-P + ~905 Bucket-X (absent from ov077) fns,
all latest-row closeness==0 -> route through family_sweep --hseq (per-sibling remap), next.
|
||
|
|
60e26e07f8 |
feat(phase-26a): A3g — propagate the 3 fleet-wide banks ×134 (bounded, gated, R22-clean)
The 3 of A3f's 33 banks that are shared fleet-wide, stamped across all 134 overlays. Done the way
the earlier run should have been: TARGETED (--addr, not --auto-from), dry-run-sized first
(3 functions × 134 members = ~400 gates, not an unbounded fleet sweep), on a clean tree at HEAD.
func_80130650 (31 ins) · func_80149450 (13 ins) · func_80174684 (9 ins) — each ×134.
dedup_propagate internal gate : 134 overlays byte-identical, 3 groups registered
R22 CLEAN-FLEET (the real proof, not the tool's incremental check that lied during the crash):
make clean + extract-all + check-all -> 136 passed, 0 failed of 136
dedup-check: 1823 -> 1826 validated, 0 failed | C1 coverage 225335/225335
DELTA (reconciles exactly):
functions byte-identical 284,559 -> 284,958 (+399 = 3 fns × 133 other overlays)
instr-weighted 66.7% -> 66.8% (+13,167 shipped .text instructions)
distinct-code 46.8% -> 46.8% (flat: propagation adds MEMBERS, not new distinct
code — the 3 bodies were counted at A3f)
403 src files (3 ×134 instantiations + engine_core.h) + config/dedup.us.yaml
The other 30 of A3f's 33 are overlay-unique (×1) and need no propagation. The larger prize remains
the ~310 byte-exact stubs in the OTHER overlays (A3e), not yet attempted.
|
||
|
|
8ffcf9646e |
feat(phase-26a): A3f — 33 functions banked that the project had written off as compiler walls
The payoff of A3e, byte-verified. These 33 sat in the backlog at closeness==0 -- match_one said
their bodies were BYTE-EXACT -- and the whole-binary gate rejected them, so they were logged as
`near`/`failed`, i.e. AS MATCHING PROBLEMS, and filed as intrinsic compiler residuals.
They were not hard. They were UNREACHABLE. gate_stage passed `--src src/<ov>/<ov>.c`
unconditionally, which restricts the byte-gate to ONE translation unit -- and every one of these
functions has its stub in a SPLIT TU. Look at where they landed:
src/ov_SC01_077/ov_SC01_077_a.c
src/ov_SC01_077/ov_SC01_077_after.c
src/ov_SC01_077/ov_SC01_077_jr_8012ACE0.c
src/ov_SC01_077/ov_SC01_077_jr_8015AE2C.c
src/ov_SC01_077/ov_SC01_077_jr_8016AB6C.c
src/ov_SC01_077/ov_SC01_077_jr_801734BC.c
src/ov_SC01_077/ov_SC01_077_jr_80178D40.c
src/ov_SC01_077/ov_SC01_077_jr_80182268.c
8 files. SEVEN of them are _jr_/_a/_after carves. NOT ONE is the main .c -- the only file the gate
was ever allowed to look at.
gate: 63 drafts -> banked 33, near 30, FAILED 0 (--no-propagate; the gate and the propagation
are different jobs, and letting an experiment tow an unbounded fleet-wide propagation is
what broke the tree an hour ago)
R22 CLEAN-FLEET: make clean + extract-all + check-all -> 136 passed, 0 failed of 136
dedup-check: 1823 validated, 0 failed | C1 coverage 224933/224933
METRICS, ×1, HONESTLY (no propagation yet -- the multiplier is still ahead):
functions byte-identical 284,526 -> 284,559 (+33)
instructions 8,470,381 -> 8,471,912 (+1,531)
fn-count % 82.79% -> 82.80%
instr-weighted % 66.7% -> 66.7% (flat: ×1 banks do not move the headline)
WHAT THIS MEASURES, beyond the 33: the backlog holds 1,588 entries at closeness==0. 1,215 have been
banked since by other paths. 373 ARE STILL OPEN STUBS WITH BYTE-EXACT BODIES. 63 of them were in
ov_SC01_077 and 33 banked -- a 52% rate on functions the ledger calls unrecoverable. The other 310
are spread across the remaining overlays: same class, same fix, not yet attempted.
Cookbook §51g LAW 11 -- a fix is not landed until its caller stops overriding it. And the reason
this hid for 26 phases, which belongs in the posterity doc: A TOOL THAT CANNOT BANK A FUNCTION IS
INDISTINGUISHABLE, IN EVERY LOG THIS PROJECT KEEPS, FROM A FUNCTION THAT CANNOT BE BANKED.
|
||
|
|
b89fcc2edc |
fix(phase-26a): A3e — gate_stage pinned the byte-gate back to 4.9%, OF A3'S OWN FIX
THE WORST DEFECT IN THE AUDIT IS NOT IN A SCANNER. It is one default argument in the CALLER of a
scanner we had already fixed.
# tools/gate_stage.py:315
summary = run_gate(a.drafts, binary=b, src=a.src or f"src/{b}/{b}.c", ...) # ALWAYS the main .c
`src` RESTRICTS the byte-gate to ONE translation unit, and _gate1 does `if src: cmd += ["--src", src]`
-- always truthy. A3 had just taught harvest_verify to DERIVE each draft's home TU *when --src is
omitted*, lifting the byte-gate's reach from 4.9% to 100%. gate_stage NEVER OMITS IT. The fix was
neutralised by its own caller's default, and the PRIMARY BANKING PATH -- every wave, the grinder, the
orchestrator, bulk_harvest -- remained structurally unable to bank 250 of ov_SC01_077's 263 stubs.
WHY IT SURVIVED 26 PHASES: harvest_verify cannot splice a draft whose stub is not in the TU it was
pointed at, so the draft never verifies -- and is then logged as near/failed, i.e. AS A MATCHING
PROBLEM. The wave reports a poor close-rate; the function goes to the backlog as a compiler residual.
A tool that CANNOT bank a function is indistinguishable, in every log this project keeps,
from a function that CANNOT BE banked.
PROOF, same draft / same gate / same second: gate_stage rejected func_80129C40; harvest_verify run
directly (no --src) VERIFIED it byte-identical and banked it.
AND A COUNTING BUG THAT HID THE HIDING (gate_stage:261): when match_one says MATCH but the whole-binary
gate rejects, the record is logged status="near" and THE COUNTER IS NEVER INCREMENTED. A 63-draft run
printed `banked 0, near 0, failed 0` -- three zeros that do not sum to 63 -- for phases. Nobody ever
added them up. (The number was not wrong. It was ABSENT.)
ALSO FIXED, sig_unify (the same disease, one level down): it SILENTLY DROPPED 190 of 196 drafts (97%).
`cur_stubs` was read from the main .c (13 of 263 stubs), so any draft whose stub lives in a _jr_ carve
hit `if fn not in cur_stubs: continue` -- dropped BEFORE THE WRITE: never copied to --out, never gated,
never logged, while the summary printed "drafts unified: 6" and read like success. THIS IS GATE_STAGE'S
STAGE-2 RECOVERY -- the pass whose whole job is to rescue the stage-1 failures -- and it has been a
no-op for nearly every draft it was meant to save. Now: TU derived per draft (corpus.stubs), canon
derived from cdecl.tu_scope (cpp -- macro-injected decls finally visible), and _keep() so an
already-acceptable decl is left alone (the §19 "sig_unify regresses canonical drafts" failure mode).
Reach: 6 -> 196 drafts; callee-externs rewritten 2 -> 90; own def-sig 2 -> 86.
MEASURED, all three consumers migrated (196 never-banked drafts):
near 5 -> 116 failed 190 -> 17
=> 173 of 190 "failures" were PLUMBING, not codegen: now compiling and SCORED instead of invisible.
THE PRIZE (measured, not claimed): the backlog holds 1,588 entries at closeness==0 -- body byte-exact
per match_one, whole-binary gate rejected. 1,215 have been banked since by other paths. 373 ARE STILL
OPEN STUBS WHOSE BODIES ARE ALREADY BYTE-EXACT, sitting in a ledger that calls them unrecoverable.
⚠ THE HARVEST ITSELF IS NOT IN THIS COMMIT, AND IS NOT CLAIMED (P9). Gating the 63 ov_SC01_077 ones
dragged `dedup_propagate --auto-from --recover` behind it; it ran >1h and hit its timeout -- its
first-ever run over the FULL corpus (A6/A7 unblocked the 407 files it could never see). It MUTATES THE
TREE BEFORE IT GATES, so the kill left 859 files + engine_core.h (+544 lines) written and UN-GATED with
the registry never updated. R22 on that tree: 44 passed / 92 FAILED -> `git checkout -- src/ config/`,
fleet restored to 136/136. Nothing lost (H4: the tree was clean, so the revert was one command).
Two real lessons, recorded: dedup_propagate is NOT crash-safe and must never run under a timeout it can
hit; and a 63-draft experiment must not drag an unbounded fleet-wide propagation behind it.
R22 clean-fleet after revert: 136 passed, 0 failed of 136. src/ and config/ clean.
cookbook §51g LAW 11: A FIX IS NOT LANDED UNTIL ITS CALLER STOPS OVERRIDING IT. After fixing a
scanner, grep every call site and ask whether a caller's default re-disables it. An audit that stops
at the callee is half an audit.
|
||
|
|
f4502f11bb |
fix(phase-26a): A3c — the recovery passes were reconciling 95% of drafts against the WRONG TU
FIRST CONSUMER MIGRATION onto the cdecl oracle — and the compiler taught me two things I had
wrong, one of which reopens a wall that has been closed since Phase 15.
1. cdecl.compatible() — "will cc1 accept these two declarations of one name?"
The predicate four tools each half-implement and get wrong: norm_sig / _norm_type collapse the
int family to ONE token, so a SIGNEDNESS change reads as "already compatible" and gets no
rewrite -- while cc1 REJECTS that redeclaration. Right about codegen, wrong about the front end,
which never reaches codegen.
2. THE ADJUDICATOR MUST BE THE COMPILER THAT COMPILES YOUR CODE (cookbook §51g LAW 9).
I wrote the rules from the C standard, then let a compiler judge. It contradicted me -- and then
the RIGHT compiler contradicted the first one. Three different answers:
declarations in one TU | standard | modern gcc | gcc-2.7.2 cc1
typedef int X; twice | error | ACCEPTS | ERROR
extern u16 X; + volatile u16 X| error | error | ACCEPTS
void X(s16); then void X(); | error | error | ACCEPTS
void X(); then void X(s16)| error | error | ERROR
--compat now adjudicates with tools/bin/gcc-2.7.2-psx/cc1, the front end that actually
arbitrates the build: 1,485/1,485 live corpus pairs agree, 0 disagree, 0 skipped.
3. THE PRIZE: the Phase-15 narrow-param wall rests on a false premise.
The no-prototype rule is ORDER-DEPENDENT. `void X(s16); void X();` COMPILES; only the reverse
fails. Phase 15 closed "the 159 arity/narrow-param conflicts" as "no clean deterministic fix --
it is simply C's default-promotion rule". cc1 does not enforce that rule in the direction the
wall assumed. Four three-line probes, 90 seconds, zero tokens. -> A10 RE-TEST TARGET.
Probe the compiler for FACTS; read its source only for LEVERS; byte-validate both. (We read
gcc-papermario for five phases believing it was 2.7.2. It was 2.8.1.)
4. THE MIGRATION: cast_call_sites canonicalized 95.1% of drafts against a TU that would never
compile them. `--src-file` is an OPTIONAL HAND-PASSED flag defaulting to src/<ov>/<ov>.c, and no
caller knows about the Phase-26 _jr_<ADDR> carves: ov_SC01_077 has 263 open stubs across 12 TUs
and only 13 are in the main .c -- while harvest_verify (A3) correctly splices into the real one.
Now DERIVED from corpus.stubs() (the INCLUDE_ASM line is self-describing), with the canonical map
derived from cdecl.tu_scope() (cpp -- so macro-injected DEFINE_func_* decls are finally visible).
Callee-conflict repair reach: 8 -> 58 of 196 drafts (7x).
5. AND THE NULL RESULT, REPORTED AS SUCH (P9/R14). Those 58 banked ZERO functions. The historical
draft tail fails on CODEGEN, not plumbing -- func_801387B8, which the audit blames on a single
unparsed `[4]`, is really 67/100 instructions off with a $s0/$s1 swap (that claim does not
reproduce on today's tree). The real gain is narrower and still worth having: 52 drafts moved
from "won't compile" to "compiles, N instructions off" -- from an INVISIBLE failure that reads as
a compiler wall into a SCORED near-miss the permuter and the §47/§48 dials can act on. That is
the audit's thesis, not a bank. THREE times in one session a confirmed mechanism produced a null
consequence.
Also: my own new audit printed "ALL ORACLES GREEN" while silently skipping 100% of its corpus (a
missing -Isrc). The exact bug class, in the tool written to hunt it. An unadjudicable check is not
a passed check.
R22 clean-fleet: make clean + extract-all + check-all -> 136 passed, 0 failed of 136
src/ untouched (0 changes) make audit-cdecl: green --compat: 1485/1485
NEXT: sig_unify + reconcile_decls carry the SAME wrong-TU bug (same --src-file flag).
|
||
|
|
f9742cf9c0 |
feat(phase-26a): A3b — cdecl.py, THE C-declaration oracle: one grammar, fifteen deleted models
Fifteen tools each carried their own regex model of "what is a C declaration", and they
disagreed — two tools in ONE pipeline disagree today about whether `extern s32 D_a, D_b;`
is a declaration at all. All fifteen shared one character class,
extern\s+([A-Za-z_][\w\s\*]*?\bD_[0-9A-Fa-f]+\s*(?:\[\s*\])?)\s*;
which cannot hold '(', ',', or a non-empty [N] — so three whole shapes were invisible to
every one of them: fn-ptr/jump-table arrays, sized arrays (one unparsed `[4]` has blocked
func_801387B8 in 134 TUs), and multi-declarators (the WHOLE line dropped, not just #2..N).
REJECTED the audit's own prescription (a shape-aware alternation per tool, ~15 coordinated
regex edits) on R33 grounds: fifteen hand-maintained models are exactly what diverged, and
an alternation only ever covers the shapes somebody remembered. The thing being scanned HAS
A GRAMMAR. C's declarator grammar is small, closed and TOTAL — it describes fn-ptr arrays,
sized/2-D arrays, multi-declarators, fn-ptr params and K&R identifier-lists without being
told they exist. ~250 lines of recursive descent: LESS code than the regexes it deletes, and
exhaustive by construction rather than by memory. (decision-log 2026-07-14.)
Two statement paths, because the inputs genuinely differ:
* tu_statements() - a TU's file scope, derived from cpp. A decl inside a DEFINE_func_*
macro body declares NOTHING until the macro is invoked (the §8c law);
a raw scan is wrong in both directions. cpp answers it exactly, in
54 ms/TU (~20 s for the fleet, cacheable).
* split_statements() - span-preserving raw split, for drafts (which get rewritten).
THREE ORACLES, whole corpus — a measurement, not a belief:
* coverage 2,952,246 depth-0 statements -> 2,731,521 declarators, 0 PARSER DEFECTS
* the real gcc 50,405 distinct declarations compiled beside this parser's reconstruction
of each one -> 0 REJECTED
* differential 0 file-scope symbols the incumbents see that cdecl misses; 26 in
engine_core.h they cannot see; 6 they wrongly promote from BLOCK scope
Two ideas worth keeping (cookbook §51g, LAWS 4-8):
* THE CANDIDATE SET IS DERIVED TOO (R33 applied to R32). At file scope C admits nothing but
declarations, so R32's over-approximating detector is *every depth-0 statement* — supplied
by the grammar, with no hand-maintained candidate regex to rot.
* GCC ADJUDICATES MY OWN COVERAGE GAP. Deciding for myself which failures "don't count" is
grading my own homework — the habit that wrote the fifteen bugs. A statement gcc ALSO
rejects is not C (my rejection is correct, the INPUT is corrupt); one gcc ACCEPTS and I do
not is MY defect. All 33 residual: NOT-C, all dead .run/drafts* scratch, none in src/.
NEW findings (docs/tooling-audit.md):
* reconcile_decls.DATA_DECL_LINE_RE finds ZERO decls in engine_core.h — it is line-anchored
and every decl there ends in a '\'. Its "authoritative tier" has ALWAYS been empty.
* gen_harvest_targets + sig_unify count BLOCK-SCOPE externs (6, byte-proven inside a macro's
function body) as file-scope canonicals — the §8d `conflicting types` confusion.
* tu_ambient's func regex ([^()]* params) drops ANY callee with a fn-ptr parameter.
* R14 near-miss: 33 drafts contain `extern if ((func_80029178(0x119) & 0xFF) != 0);`, written
by a RECOVERY TOOL — but the source bug was already fixed in Phase 19 (0 garbage / 300 sigs
today). Mechanism confirmed, consequence nil. Note what it cost while live: a draft that
cannot compile fails the byte-gate and reads downstream as an INTRINSIC COMPILER WALL.
Bugs the oracles caught in ME (and would otherwise have shipped): `extern s32 (*D_801274D0)(s32);`
parsed the BASE TYPE as the name; a K&R declaration-list flushes as SEVERAL spans, so the body
attached to the wrong one and leaked the K&R parameter names into file scope as fake globals.
SCOPE, deliberate: NO consumer is migrated here, so this cannot move a byte. The audit warns
that making the parser see more ARMS dormant transforms (reconcile_decls.data_access_subs would
mangle `D_1[i]()` -> `((u8 *)D_1)[i]()` the moment fn-ptr decls become visible to it). Migration
is one tool at a time, each byte-gated.
R22 clean-fleet: make clean + extract-all + check-all -> 136 passed, 0 failed of 136
make audit-corpus: 0 PHANTOM + 0 TRUNCATED make audit-cdecl: ALL ORACLES GREEN (new gate)
|
||
|
|
c7772bc452 |
docs(phase-26a): SESSION-9 CLOSE — cookbook §51 (the tooling-integrity laws) + handoff
R30/R16: the context-dependent artifacts, written while the context is live.
cookbook §51 — the SILENT SKIP: the bug class, why the byte-gate cannot see it, the
over-approximating-detector method, and FOUR LAWS:
1. Derive, don't re-derive — the best outcome is a DELETED SCANNER (28 findings -> one
derived oracle + ~10 deleted scanners). A derived fact cannot rot; a hand-maintained
copy of it is a liability that grows with every structural change.
2. Assert your COVERAGE, not merely your correctness. *** A LOUD FAILURE THAT NOBODY
COUNTS IS EXACTLY AS INVISIBLE AS A SILENT ONE *** — build_engine_types printed
'[overlap] handle manually' every single time for four phases while dead on 81% of its
own corpus. This CORRECTS the first draft of R32 ('fail loud'), which was not enough.
3. When an oracle is structurally blind to a class of error, add a SECOND ORACLE THAT CAN
DISAGREE WITH IT — not a better assertion inside it. We had two all along and never made
them argue. (And scope the comparison to where the second oracle is genuinely independent:
the same check run outside its domain reports 914 slices when the truth is 193.)
4. A rule that needs a human to remember it is not a gate. Make it structural.
+ the FALSE-WALL PIPELINE (a silent skip -> a wasted draft -> a backlog 'matching failure'
-> reserved_walls() PERMANENTLY blacklists a function that was never attempted), and a
checklist for any new corpus-scanning tool.
CURRENT_PHASE: session-9 handoff — what is done, what remains (each with its spec on disk),
and the R32-corrected / R33 / R34-new rule candidates for P10 ratification.
|
||
|
|
82d79e7a32 |
fix(phase-26a): A6/A7 — the family engine could not see half its corpus; 17 fns banked x134 free
R22: check-all 136 PASSED / 0 FAILED. dedup-check 1823 validated / 0 failed (C1 coverage 224,933/224,933).
Fleet instr-weighted 66.5% -> 66.7%.
=== dedup_propagate: it was blind to HALF the corpus ===
overlay_files() used a hardcoded suffix allowlist ("_a","_o0","_o0b","_after") that predated the
Phase-26 jr carves -> 404 of the fleet's 811 overlay .c. The 407-file gap held 36,135 INCLUDE_ASM stubs
and ~32,000 inline defs, and overlay_files gates ALL of dedup_propagate (source_text / find_site /
apply_plan / struct_check / reconcile_caller_extern). Now a GLOB — never an allowlist, because the NEXT
split family would re-open it. The asm_subdir is always the file stem, an invariant the old four entries
already satisfied.
find_site's def-detector required the signature line to END in ')' and the next non-blank line to START
with '{'. It therefore silently dropped THREE shapes: K&R definitions (`s32 f(arg0)` / `s32 arg0;` / `{`),
multi-line signatures, and single-line bodies. K&R is the project's house style for exactly the biggest,
highest-reach functions — func_8015AE2C (562 ins), func_80166994, func_80133CD4, func_8015A3C8 — and they
live in the _jr_* files overlay_files could not even open. Fixing either alone would have been useless:
the glob exposes the files, and find_site would still drop their biggest prizes. Both fixed together.
* The signature's closing paren is now found by a real paren-walk, not line.count() or split(')')[-1]:
a single-line body containing a call (`void f(int a){ g(a); }`) has balanced parens of its own, so
both shortcuts land on the WRONG paren and then misread the body's ';' as a prototype terminator.
* AGREEMENT ASSERTION (the audit's): find_site vs family_remap.extract_unit -> 701 agree / 0 disagree.
Negative controls hold (a prototype+call is rejected; a 1-line body with a call is a def).
=== THE HARVEST (free work, byte-gated) ===
--auto-from ov_SC01_077 now nominates what it could never see: 20 planned, 17 propagated x134, 3 dropped
as cross-overlay stragglers. 134 overlays rebuilt BYTE-IDENTICAL; 17 new dedup groups.
Includes ALL FOUR functions A1 caught the registry lying about (func_80128ED8 / 8012C098 / 8012C0EC /
8012C750): 0 stubs remaining, real shared macros. THE LOOP CLOSES — A1 found the lie, and THIS is the
bug that had made it true (3 of the 4 are defined in ov_SC01_077_jr_8012ACE0.c, which the allowlist could
not open, so the propagation never ran and dedup_integrate greenlit the result).
=== family_remap: 96 PHANTOM exemplars -> 0 ===
extract_unit globbed only src/<ov>/<ov>*.c, so a function matched via a SHARED body had no source form
and read as NOT MATCHED. 93-96 of 218 h_seq "matched" exemplars were phantom, carrying 2,157 candidate
members of which 1,834 are still-stubbed, PURE/IMM-clean, symbol_map-clean and unpinned — staged and
gated today, dropped before the first build then. It is now TOTAL over BOTH shared-body mechanisms:
(1) the DEFINE_func_<ADDR>() macro — reconstructed as the exact INVERSE of dedup_propagate.make_macro
(derived from the generator, not re-guessed from the text);
(2) a DIRECT definition in a shared header, #included per overlay — the whale (func_80144B9C, 770 ins,
-O0), which the registry explicitly records as "NOT a DEFINE_ macro".
CENSUS: 216 matched exemplars, 216 real, 0 PHANTOM.
symbol_map named the symbol by HOW IT WAS LOADED, not by WHAT IT IS: reloc_targets labels every lui/%lo
pair "data", and a FUNCTION's address taken via lui/%lo (an address-taken callback) is exactly that shape
(splat's own .s: %lo(func_8017E1D4), 7 occurrences). The map got a D_<ADDR> key while the C writes
func_<ADDR>, so the word-bounded substitution matched NOTHING and silently no-op'd — the sibling kept the
EXEMPLAR's function pointer and the loss was booked as a BYTE failure, indistinguishable from a compiler
wall. Now emits both keys (addresses are unique; the pass is simultaneous, so the extra key is free).
gather_externs was line-oriented, so a WRAPPED comma extern was invisible in both directions (the first
line has no ';', the continuation has no `extern`). ov_SC01_077.c:271-272 declares NINE symbols that way,
and the exemplar referencing them (func_8013D178) is a 133-member family — every sibling was staged with
NO declaration, failed to compile, and bisect-stormed its whole gate group. Now statement-oriented, and
an unresolved symbol is REPORTED, never silently dropped.
=== family_sweep.stub_map / build_engine_types ===
stub_map: func_-only -> a curated-name stub read as "already matched" -> phantom exemplar. Now corpus-derived.
build_engine_types hard-exited on 1,070 of 1,470 type-bearing overlay .c (73%; the audit measured 573/709
= 81% on its narrower set) because 1,929 TAGGED-struct typedefs tripped a guard whose own comment asserts
"our source has only ANONYMOUS-struct typedefs" — true in Phase 20, false since the harvest agents started
writing tagged structs. inject_capped_externs routes every type-bearing body HERE as the type-heavy tail's
ONLY sanctioned unblocker, so the tail's unblocker could not run on the corpus the tail lives in.
A contained def (the typedef's span encloses the body) is liftable — it just must not be counted twice;
only a PARTIAL overlap is malformed. Verified on a file that used to hard-exit: 5 tagged typedefs folded +
forward-declared, 46 types written, exit 0.
** AND THE SHARPEST LESSON IN THE AUDIT: this one was never silent. It printed "[overlap] ... handle
manually" every single time. But the message reads like a rare edge case rather than a four-fifths
coverage failure, so nobody ever COUNTED it. A loud failure that nobody counts is exactly as
invisible as a silent one. R32 must be "assert your coverage", not merely "fail loud". **
R14 self-catches, recorded because I hit both while fixing them: my first shared-header scan read a macro
body's `extern void f(void); \` as a DEFINITION (the trailing continuation means the line does not end in
';', so the decl guard never fired) — the exact bug fixed at commit:0552, reintroduced by me and caught only
because the whale resolved from the WRONG file. Column-0 anchoring fixes it by construction. And my
phantom census returned 0/0 twice because I guessed the manifest schema instead of reading it.
|
||
|
|
af2f40d153 |
fix(phase-26a): A4/A5 — 193 unmatchable slices dissolved; the closeness oracle stops lying
R22 CLEAN-FLEET: make clean -> extract 136 -> build 136 -> check-all = 136 PASSED, 0 FAILED.
make audit-corpus: 0 PHANTOM + 0 TRUNCATED (was 193).
=== A4: a CORPUS defect the byte-gate could never have caught ===
config/symbols.us.txt:981 declared `listCdBuffer = 0x80180000` — a correct Phase-3 name for MAIN's
LIST.CD RAM buffer. But that address is OUTSIDE main's image and INSIDE the overlay slot, and every
overlay's splat config stacks symbols.us.txt. High RAM is REUSED: an address that is a buffer to main
is live CODE to an overlay. So splat saw a symbol boundary mid-code and, across 97 of 134 overlays:
* CUT 97 REAL FUNCTIONS IN HALF (a head ending on a `lui`, no return), and
* INVENTED 96 PHANTOM ONES (a tail beginning by reading the assembler temp $at).
193 slices NOBODY COULD EVER MATCH — not "hard", not "a compiler wall": unmatchable by construction.
They sat in the harvest queue as ordinary work, so agents would burn on them forever and the failures
would be filed as intrinsic compiler residuals.
The phantom listCdBuffer.s in ov_SC01_005 literally begins:
lw $ra, 0x10($sp) / addiu $sp, $sp, 0x18 / jr $ra
splat cut a function immediately before its EPILOGUE and called the epilogue a function.
AND IT HAD ALREADY CONTAMINATED REAL WORK: in ov_SC03_031 the cut landed where the epilogue was
exactly `jr $ra; nop`, so the Phase-26 x134 sweep innocently BANKED the phantom as
`void listCdBuffer(void) {}` — byte-correct, gate-green, entirely fictitious — while leaving
func_8017FFC4 permanently unmatchable. Removed.
WHY NO GATE CAUGHT IT, AND WHY THAT IS THE POINT: INCLUDE_ASM pastes the two .s halves back VERBATIM
in original order, so the image is byte-identical either way. The byte-gate was green the whole time
and always would have been. It is a perfect CORRECTNESS oracle and a NULL COVERAGE oracle. No
assertion added INSIDE it could ever have found this. What found it was a SECOND, INDEPENDENT oracle:
tools/sig_image.py derives boundaries from the ORIGINAL bytes without splat, and DISAGREED with the
corpus (58,524/58,621 agreement with spimdisasm; correct on all 97 disagreements).
=> When one oracle is structurally blind to a class of error, the answer is not a better assertion
inside it. It is a SECOND ORACLE THAT CAN DISAGREE WITH IT. (`make audit-corpus` is now that.)
THE RULE (the mirror of R13/R15, never written down): a symbol whose address falls inside ANOTHER
binary's vram window must never enter that binary's symbol stack.
FIX: config/symbols.us.ram.txt — main-scoped symbols outside main's image — stacked ONLY by
config/splat.us.exe.yaml. Main keeps the name it needs (10 %hi / 11 %lo refs; 143dbb89 byte-identical);
the overlays never see it. Exactly one symbol was in scope fleet-wide; the resident window was clean.
AND A REAL FUNCTION THE ACCIDENT WAS HIDING: in ov_SC01_084 / ov_SC02_041 / ov_SC03_094 / ov_SC06_008
there IS a genuine function at 0x80180000 (111 / 35 / 28 / 74 ins), reachable ONLY via a fn-pointer
table (.word func_80180000) and never by `jal` — so splat cannot find it and needs the boundary
DECLARED. listCdBuffer had been supplying it by luck. Now declared honestly, per-overlay, in
config/symbols.<ov>.txt — exactly where R13/R15 says an overlay-scoped symbol belongs.
=== A5: the closeness oracle every crack agent trusts was lying on 155 functions ===
masked_diff._reloc_kind() knew 26/HI16/LO16. An over-approximating sweep of every reloc objdump emits
across all 3,367 build objects found FOUR: R_MIPS_26, HI16, LO16 — and R_MIPS_PC16 (211). PC16 fell
through to a FULL-WORD compare, but the object holds an UNRESOLVED PLACEHOLDER in the branch
displacement, so that compare can NEVER succeed.
DECISIVE TEST (derived from the invariant, not from reading the regex): INCLUDE_ASM pastes the
ORIGINAL asm, so for every stub diff_object_s() MUST be 0. Measured, coverage-asserted:
2,741 functions scored — old mask: 150 LIES; PC16 masked: 4 LIES.
(The 4 survivors are the separate length-delta defect.) A phantom non-zero sends an agent to grind at
a wall that is not there, and the wasted attempt is then booked as a MATCHING failure, feeding
reserved_walls() and PERMANENTLY BLACKLISTING a function that was never broken.
=== NEW FINDING (found by cutting the R22 corner): a STALE OBJECT CAN PRODUCE A FALSE PASS ===
`.o <- .s` is not a dependency make can see: assembly arrives via INCLUDE_ASM, expanded to a `.include`
consumed by maspsx/as AFTER cpp, while -MMD tracks headers only. Re-extract, build incrementally, and
make links a STALE object. This is not merely slow — INCLUDE_ASM pastes the ORIGINAL bytes, so a stale
object still yields the original image: SHA1 GOES GREEN while the split just changed is never exercised.
A broken config change can be "verified" by an incremental build. Live proof: 8 of 136 binaries linked
stale objects here; they failed LOUDLY ONLY BY LUCK (the dead symbol was an undefined reference) — a
merely-different-but-valid split would have gone green on all 136.
R22/H3 already legislate this, and I broke them. But a rule that needs a human to remember it is not a
gate. FIX: `extract` now invalidates the objects that include what it just rewrote (main's are top-level,
so -maxdepth 1 — verified it cannot clobber the other 1,605 objects). Structural, not advisory.
R14 self-catch, recorded: my first A5 test passed `fn=` to diff_object_s(), which takes two args; the
TypeError was swallowed by my own `except Exception: continue` and it reported 0 scored / 0 lies. I
wrote the exact bug I was auditing, inside the test for it. Caught only because 0 looked wrong. The
test now asserts its own coverage.
|
||
|
|
9794b13ed2 |
fix(phase-26a): A3 — the endgame plan was 2.8x too big; the matched set is now DERIVED
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.
|
||
|
|
a302908f24 |
fix(phase-26a): A3 — target selection was blind to 91.6% of the remaining work; now derived
The audit's CRITICAL finding, fixed at the root. Both tools now derive the corpus from
tools/corpus.py instead of keeping their own decaying copy of the tree layout.
build_fuel_manifest.live_stubs() — a hardcoded 3-file dict {<ov>.c, _a.c, _o0.c}. ov_SC01_077 has
FOURTEEN .c files, so it saw 30 of 264 stubs AND REPORTED SUCCESS. Everything downstream consumes
this manifest — worklist.py (100% of its rows), wave_targets.py (100% of its pools) — so:
targets 30 -> 263
reach-134 targets 10 -> 127 (the ENTIRE high-ROI band was invisible)
remaining gain 83,305 -> 994,633 instructions
994,633 is the A2 audit's predicted figure TO THE UNIT — a fourth independent confirmation
(auditor -> skeptic -> corpus.py -> this). Four of the five highest-leverage functions in the whole
project sit in split regions no tool could see; the top one, func_80178004 (165 ins x reach 134 =
22,110), had never been nominated by anything.
It rotted SILENTLY: .run/fuel_manifest.json (Jul 8) recorded 130 stubs; the same code today returns
30, because the Phase-26 jr splits moved ~100 stubs out from under a dict literal last edited in
Phase 22. Nobody noticed, because a target that is never nominated produces SILENCE, not an error.
wave_targets.REGION_SUB / asm_for() — a 3-entry dict with a silent fallback to the main subdir.
ov_SC01_077 has TWELVE asm subdirs, so 78 of the 87 targets any --class wave emitted handed a
drafter an asm path THAT DOES NOT EXIST. The drafter then drafts against nothing, and the wasted
attempt is booked in the backlog as a *matching* failure — which feeds reserved_walls() and
PERMANENTLY BLACKLISTS a function that was never actually attempted. A silent skip compounding into
a false wall. Now 263/263 asm paths resolve, 0 missing; asm_for() raises rather than guess.
Also: --region's 3-value whitelist defaulted to 'main', which sees 13 of 264 stubs even with a
correct manifest -> default 'any', free-form.
R33 throughout: the INCLUDE_ASM line is SELF-DESCRIBING (its first argument IS the asm subdir,
because splat wrote it there), so both dicts were second copies of a fact the tree already states.
A dict literal is strictly worse than the filesystem AND it fails OPEN. Never re-introduce one.
No build impact (selection/report tools only); docs/worklist.md regenerated with the honest numbers.
|
||
|
|
ffb6f1a40f |
docs(phase-26a): A2 — the full audit; 28 findings survive; the endgame plan was majority-fiction
38 agents / 2.24M tok / 0 err. 32 findings raised -> 28 SURVIVED adversarial verification
(4 REFUTED, 16 downgraded). 40 scanners measured CLEAN. Full write-up: docs/tooling-audit.md ROUND 2.
THE ROOT CAUSE — one bug, ~10 times: a hand-maintained model of the corpus layout (a file
allowlist, a single-.c assumption, a func_-only regex, a REGION_SUB dict) sitting on top of a
filesystem that already answers the question. Every TU split silently widened it.
DECAY PROVEN: .run/fuel_manifest.json (Jul 8) recorded 130 stubs; the same tool today returns 30.
The Phase-26 splits moved ~100 stubs out from under a dict literal last edited in Phase 22 — and
nobody noticed, because an un-nominated target produces SILENCE, not an error.
MEASURED: 91.6% of ALL remaining project gain is invisible to target selection (true 994,633 ins;
the manifest sees 83,305). 117 of 127 reach-134 fns never nominated. harvest_verify cannot see
56,742 of 58,717 (96.6%) open stubs. wave_targets hands 78 of 87 targets a nonexistent asm path.
THREE RESULTS OVERTURN SETTLED CONCLUSIONS:
1. Phase-22's 'the permuter's fuel is exhausted' is UNSAFE. grinder banks through harvest_verify,
which sees ONE TU — 1,290 of its own 1,298 queued fns live in another. 99% could never have
banked. '0 banks since Phase 21' is equally consistent with 'the tool could not bank'.
2. The Phase-25/26 endgame plan is MAJORITY-FICTION. family-manifest.md advertises 2,758
multi-member families / 11.0 MB; 1,071 of them / 6.80 MB (62% of the byte-weight) are ALREADY
FULLY MATCHED. The ranking — the file's whole purpose — is sorted mostly on dead work.
3. A CORPUS defect the byte-gate is structurally blind to: symbols.us.txt:981 puts a main-EXE DATA
symbol (listCdBuffer = 0x80180000) into every overlay's symbol stack, but in overlay space that
address is CODE. splat cuts 97 real functions in half and invents 96 phantom ones = 193 slices
NOBODY CAN EVER MATCH, in 97 of 134 overlays — and the build stays byte-identical and green,
because the .s halves are pasted back verbatim. A perfect correctness oracle, a null coverage
oracle. What saved us: sig_image was RIGHT (58,524/58,621 vs spimdisasm; correct on all 97
disagreements). A SECOND INDEPENDENT ORACLE is the only reason it was visible at all.
FIX RESTRUCTURED around the root cause: ONE derived corpus oracle (A3) + ~10 DELETED scanners —
not ten fixed regexes. Plus the listCdBuffer corpus fix (A4) and the closeness oracle (A5, which
lies on 155 functions, feeding false walls into reserved_walls()).
decision-log (R31): the why, and the design lesson — a derived fact cannot rot; a hand-maintained
copy of it is a liability that grows with every structural change. We had no instrument that could
report ABSENCE: every gate we owned answered 'is this right?', none answered 'is this all?'
|
||
|
|
bb65d36341 |
fix(phase-26a): A1 — dedup_integrate was a gate that could print a FALSE GREEN
The audit's priority #1: a fail-closed byte-honesty validator whose silent skips nothing downstream can catch. Three false-green paths, all measured, all now fail-closed with negative controls. R33 FIRST (derive, don't re-derive). The registry makes two claims; the tool only ever checked one, and mis-described that one: C1 EQUIVALENCE ("these vrams hold the same code in the ORIGINAL") — checked against the sigs, which sign the ORIGINAL bytes. KEPT. But the docstring claimed it also caught SOURCE drift: it cannot. A sig is a property of the ROM, immutable w.r.t. src/. Source drift is caught by the BUILD. Docstring corrected (P9). C2 BANK ("matched once in the source header, instantiated at every member") — NEVER CHECKED. Now DERIVED from the build invariant: INCLUDE_ASM pastes the ORIGINAL asm, so a member NOT wrapped in it is byte-exact, and one that IS wrapped is not banked — whatever the registry says. C2a: the group's macro token must occur in its source file. C2b: no member may still be an INCLUDE_ASM stub. THE THREE FALSE GREENS 1. 1808 groups claimed a DEFINE_func_* macro; only 1801 exist. The 7 ghosts printed [ OK ] — hiding 532 member-instances / 22,344 instructions of REAL, UNBANKED work (4 fns matched in ov_SC01_077, still INCLUDE_ASM in the other 133 overlays). 2. An absent .run/sig.<bin>.jsonl degraded to "0 validated, 0 failed" and EXIT 0. On a fresh clone the gate validated NOTHING and passed. Now fails; --allow-unsigned is the escape. 3. The bank claim was never checked at all. THE CAUSAL CHAIN (the audit's thesis in one example). 3 of the 4 hidden fns are defined in ov_SC01_077_jr_8012ACE0.c — a _jr_* split file. dedup_propagate.overlay_files allowlists only ("_a","_o0","_o0b","_after"), so the propagator could not SEE them; the group was registered anyway; dedup_integrate greenlit the lie. TWO silent-skip bugs compounding: one created the hole, the other hid it. Harvest fuel -> .run/audit/a1_harvest_fuel.json, banked in A5. BLAST RADIUS, MEASURED NOT PREDICTED (R14). Headline metrics UNCHANGED to the decimal (instr-weighted 66.5%, distinct-code 46.8%) — weighted_metrics() derives from the invariant and was structurally immune to the lying registry. FLEET REAL substantive unchanged (282,466): progress.py had already been taught to distrust it (commit:0574). Only dedup_integrate still believed it. A null result that CONFIRMS R33: the tool that refused to re-derive was the one that was right. - registry repaired: 1813 -> 1806 groups (7 ghosts removed; instances 223,725 -> 222,787) - make report GREEN end-to-end: 1806 validated, 0 failed | C1 coverage 222,787/222,787 signed - negative controls: stubbed member -> exit 1; missing sig -> exit 1; --allow-unsigned -> exit 0 - report-only tool: no compiled artifact depends on it, so no R22 clean-fleet is owed here |
||
|
|
978ef703ac |
docs(phase-26a): A0 — the tooling-integrity audit, as an INSERTED HALF-PHASE (Drew's call)
- Drew (2026-07-14, gate 1): run the audit inside Phase 26, then resume at Task 7. Declined the alternative (close Phase 26 early on an unmet milestone -> Phase 27): the audit is a PREREQUISITE to structural completion, not a successor to it — the tooling that MEASURES the milestone is the thing at fault. Phase-3.5 precedent. - CURRENT_PHASE.md: the Phase 26-A block (A0-A11), built FROM docs/tooling-audit.md (40 measured findings), R33-before-R32 ordering — the best outcome is a DELETED scanner, not a fixed regex. - decision-log (R31): the why, the structural blind spot (a scanner extracts N, the true count is M > N, and nobody ever compared N to M — the byte-gate is a perfect CORRECTNESS oracle and a NULL COVERAGE oracle), and A1's first finding. - harness task list built (R28). |
||
|
|
9a94e9ba46 |
docs(phase-26): docs/tooling-audit.md — the 40 measured findings, made DURABLE (R30)
The audit's evidence (6 agents + 6 skeptics, 1.2M tokens, 40 findings with file:line proof and measured candidate/parsed/skip counts) existed ONLY in a workflow journal OUTSIDE the repo. A fresh session would have inherited my SUMMARY of the audit, not the audit — exactly the R30 failure mode (capture context-dependent artifacts DURING the session that produced them). Drew caught it. Now committed as the plannable input to the audit phase, with: - the method (measure found-vs-candidates against an OVER-approximating detector; never "review the regex" — that is the failure mode that wrote these bugs); - why it gates the matching work (the byte-gate is a perfect CORRECTNESS oracle and a NULL COVERAGE oracle: green since Phase 5 at 0% decompiled, so it is compatible with ANY decomp %); - THE QUESTION IT ANSWERS: how many walls we have already "byte-proven" across 26 phases were lookup misses wearing a wall's clothes? (the def-side loose-typing wall, the 159 arity conflicts, the type-heavy tail were ALL diagnosed on top of the 10% callee-oracle hole); - R32 (coverage assertion) + R33 (derive, don't re-derive — apply FIRST: the best outcome is a DELETED scanner, not a fixed regex); - the priority order (dedup_integrate FIRST — a fail-closed validator that can print a FALSE GREEN); - the 7 bugs already fixed (do not redo) and the 63 tools not yet audited, with the filter for which matter. |
||
|
|
6e8c459ade |
docs(phase-26): SESSION-8 CLOSE — checkpoint for a fresh session; the tooling-integrity audit gates what comes next
RESULTS. Fleet instr-weighted 63.0 -> 66.5%, distinct-code 39.1 -> 46.8%, fn-count 82.61%.
FINAL R22: make clean + extract-all + check-all -> 136/136 BYTE-IDENTICAL, 0 coverage defects.
dedup 1813/0. 0 NON_MATCHING (G4). 31 commits.
13 CORES CRACKED incl. the four heaviest functions in the game (952/890/562/536 ins). The 12-agent
Ultracode wave returned 11/12 first-pass MATCH, each adversarially verified (a skeptic re-ran match_one
+ the §8a jump-table check). Banked x134 this session: func_8015AE2C, func_80178D40, func_8015A3C8,
func_8013FFD8, func_8016AB6C, func_8015444C, func_801380E0 (+ func_8017BEBC x1).
THE TOOLKIT CROSSED A LINE — three ZERO-BYTE DIALS now cover the three passes that produce essentially
every "irreducible" residual, each with a diagnostic signature a cheap agent recognises on sight:
registers rotated -> global.c allocno priority -> §47 slider / §48-A pricing dials
two insns swapped, SAME regs -> sched.c rank_for_schedule LUID tiebreak -> §49 LUID dial
structure right, count wrong -> loop peel / cross-jump -> §46 / §48-D
That is why 9/12 fell first-pass to ORDINARY agents. Fable5 DISCOVERS a class; everyone else APPLIES it.
New: §46 §47 §48(+A4) §49 §50. Read §50-B before using §48-A1/A4 — it BOUNDS them (the "cross_jump
refunds the bytes" claim is FALSE for a 1-insn tail reached by two jumps; jump.c:1993 minimum=2).
DREW'S DIRECTIVE (binding): the TOOLING-INTEGRITY AUDIT comes BEFORE any further matching work, and is
NOT part of this phase. First act of the fresh session is a Tier-1 phase-boundary call (close Phase 26
early, or run the audit as an inserted phase — Drew decides).
WHY: seven silent-skip tool bugs in one session, and they are a STRUCTURAL blind spot — a scanner
extracts N items, the truth is M > N, and nobody ever compared N to M. The byte-gate is a perfect
CORRECTNESS oracle and a NULL COVERAGE oracle: it has been green since Phase 5 at 0% decompiled (
INCLUDE_ASM pastes the ORIGINAL asm), so a green gate is compatible with ANY decomp %. One 10% hole in
the callee oracle made NINE byte-exact functions look like an intrinsic compiler wall. The real question
the audit answers: how many walls we have already "byte-proven" across 26 phases were lookup misses
wearing a wall's clothes? (The def-side loose-typing wall, the 159 arity conflicts, the type-heavy tail
were ALL diagnosed on top of that hole.) Audit scope so far is 19 of 82 tools (23%), by risk — NOT
comprehensive; dedup_integrate.py is unaudited and can print a FALSE GREEN.
RULE CANDIDATES (P10, Drew ratifies at PhaseEnd):
R32 Coverage assertion — a corpus scanner must assert its own coverage and fail loud on unparsed input.
R33 Derive, don't re-derive — where a proven invariant answers the question, derive from it. The best
audit outcome is not a fixed regex; it is a DELETED scanner.
SELF-CORRECTION ON THE RECORD (P9/R14): I told Drew the headline numbers under-reported by ~190k
instructions. WRONG. weighted_metrics() never calls classify(), so it was structurally immune; the
published numbers were correct all along. I verified the DEFECT but not its BLAST RADIUS. A null result
against a strong prediction is a refutation — chase it.
|
||
|
|
4e1ec84028 | docs(phase-26): decision-log — Drew: the tooling-integrity audit GATES further matching work and gets its own phase (fix the instrument before taking more readings) | ||
|
|
8079240216 |
docs(phase-26): cookbook §50 — refinements that BOUND §47/§48 (from the func_80135EB0 wall)
The one wave core that did not close still paid for itself: - §50-A the exact §47 priority encoding: pri = floor_log2(refs)*refs*size/(death-birth), birth/death = 2*insn_number, DEATH IS 2*M NOT 2*M+1; ties break by ascending qty = BIRTH ORDER. A tie you can compute is a tie you can break. - §50-B ** BOUNDS §48-A1/A4 **: 'cross_jump refunds the bytes' is only true for tails >= 2 insns, or when one path FALLS THROUGH. jump.c:1993 calls find_cross_jump(minimum=2) and does not count the jumps themselves, so two j's with a 1-insn common tail will NOT merge. Check the tail length before using A1/A4. - §50-C an s16 param + 'x|1' manufactures a poison temp (ior->T; sll; sra); s32 does not (combine reuses i2dest). Widening a parameter can DELETE an allocno. - §50-D copy preferences beat plain preferences and need a BLOCK BOUNDARY (combine's LOG_LINKS never cross blocks). - §50-E maspsx/gas MERGES lui $at for two stores to the same 64K page — which is why the original interleaves its global stores. Never 'tidy up' the store order of a matched function. - §50-F the documented wall: a local-alloc qty_compare_1 race needing a reload-deleted no-op copy in a specific range. |
||
|
|
7e7c80659b | docs(phase-26): decision-log — the audit's finding was real, my reading of it was wrong; derive metrics from invariants, don't re-parse the world (R14/P9 self-correction) | ||
|
|
a30500eecf |
docs(phase-26): cookbook §49 — the LUID DIAL (func_8017A4AC MATCH, 536 ins ×134, the biggest remaining fn)
The sched.c analogue of §47's live-length slider. A close=2 with IDENTICAL registers is not a regalloc residual — it is sched2's rank_for_schedule falling through to its final tiebreak, 'return INSN_LUID(tmp) - INSN_LUID(tmp2)', i.e. position in the .greg stream. Root cause is upstream in sched1: adjust_priority/birthing_insn_p gives every register-DEFINING insn LAUNCH_PRIORITY 0x7f000001 (sched.c:2574), which sinks the un-boosted insn past its rivals and inverts the LUID order. THE DIAL: materialize a call argument's sign-extension into an explicit s32 temp, placed AFTER the intervening statement (adjacent to the load, combine fuses lhu+sll+sra into one lh and you LOSE 3 insns; the intervening store blocks the fusion). Widen the prototype to (s32,s32) so the call adds no conversion. Same instructions emitted, earlier INSN_LUID -> the tie flips. Zero-byte dial family is now three: §47 live-length (global.c), §48-A1/A4 sink-init/sink-call (global.c/local-alloc), §49 LUID (sched.c). Method: -dS -dR dumps the ready lists + priorities; equal priorities => you are on a LUID tiebreak => the fix is PLACEMENT, not registers. 11 of 12 wave cores now MATCH. |
||
|
|
0bf0313a6d |
docs(phase-26): cookbook §48-A4 — SINK THE CONSUMER CALL INTO THE ARMS (func_8016AB6C MATCH)
The inverse of A1: A1 sinks an INIT to shorten a live range; this sinks the CONSUMER to delete the allocno outright. A value defined in both if/else arms and consumed only by a call at the join becomes a cross-block global allocno whose copy-prefs include the ARG register — and find_reg's copy-pref override scans ascending regno (NOT reg_alloc_order), so $5 deterministically beats $16. The only escape is allocno_calls_crossed>0 (global.c:906 strips caller-saved prefs), which a pseudo defined after one call and dead before the next does not get. Duplicating the consumer call into the arms demotes it to a call-crossing BLOCK-LOCAL -> local-alloc gives it a callee-saved reg, preserving the §48-A2 $s0 occupant; the identical post-reload tails are re-merged by cross_jump, so the duplication costs ZERO bytes. 10 of the 12 wave cores now MATCH. |
||
|
|
5aea9b1112 | docs(phase-26): decision-log — promote the silent-skip lesson from a rule to a MECHANISM (coverage oracles); flag the verdicts reached on top of the broken oracle (Drew approved) | ||
|
|
29478ab9b0 |
docs(phase-26): cookbook §48 — the 12-core jr crack wave (9/12 MATCH): allocno-pricing dials, the EBB rule, type-driven codegen, the cross-jump ratchet
- §48-A allocno-PRICING DIALS (global.c:594): sink an init into the if/else arms to collapse a live-range and RAISE priority byte-neutrally (cross_jump re-merges the tails after regalloc); the local-alloc $s0 occupant that pushes arg0 to $s1; block-scoped per-case temps as a local-alloc tie gate (local-alloc.c:1765 refuses to tie a multi-block pseudo). - §48-B THE EBB RULE, the general form of §46-L2: anything that must survive cse needs its def and uses in different extended basic blocks — reg-reg copies, held global addresses (la $sN in a loop preheader, def at loop top + use inside a jtbl-reached case), pointers-to-global across calls. Corollary: a pointer-to-global survives only if EVERY use is at offset 0 (fold_rtx folds sym+k). - §48-C the C TYPE selects the addressing mode: scalar global -> lui/%lo, struct global -> la+offset; lwl/lwr block copy == a plain assign of a 2-byte-aligned struct (mips.c:output_block_move needs align>=4 for the lw/sw arm); the dead-sibling-scalar trap (cost 108 ins — use a real array). - §48-D the CROSS-JUMP RATCHET: two cases needing opposite branch senses cannot be a mirrored if/else — cross_jump + jump.c's invert-over-uncond-jump collapse them into one. Use gotos into labels inside the other case. - 9/12 first-pass MATCH by ordinary agents applying the map. Fable5 discovers a class; everyone else applies it. |