Commit Graph

1276 Commits

Author SHA1 Message Date
Drew T d71836107c phase-36: T7 agent a3 — func_801397B0 not closed (best 2), its reading toolified as R18 the bystander move
The third agent produced no bank and a precise refutation plus a generator, which is the deliverable the brief asks for.

- it refuted the a2 hypothesis on its own body: git grep returns 1,770 declarations in two forms, both (s32 a0), no (void)
  anywhere, and the pin is on a local rather than the parameter. Three lever-free spellings reach the target's complete
  register assignment, so the class is reachable from plain C.
- its best is score 2, class ORDER, 89/89 instructions, every register correct, one displaced bystander store. The target's
  sw sits inside the lbu->addiu window and that position is forced: anti_dependence and true_dependence (sched.c:817/845)
  both hold, so the store can neither hoist nor sink. Post-sched1 stream and reg_live_length then match ours, leaving
  reg_n_refs — computed by flow on the pre-combine RTL — as the only remaining input.
- R18 moves one simple statement to each other position in its own block, up to six away. R9's adjacent swap is the special
  case; the distance is the point. It costs no instruction where R7's LOOP notes are a full sched1 barrier and always cost
  one displaced insn, so R18 is ranked ahead of R7 in every class.
- two wrong spellings before the known-true check passed: identifier-disjointness as a requirement offered three candidates
  and none of them the agent's (it is only an ordering preference now — byte-identical output is the same program, so the
  oracle is the whole correctness proof, which is R9's own footing), and a blank line counted as an obstacle, so the
  generator never offered the very move it was written from. It now reproduces that body exactly: bystander @21->17.
- delever_pack.py now writes each trace candidate's residual class beside its score, from the agent's method note: a bare
  number hid that a move had already turned this body's residual from REG into ORDER.
- delever --selftest OK (3 new controls incl. the nested-block refusal); delever_search --selftest OK; tool_census OK.
2026-09-10 04:26:00 -06:00
Drew T 3ba4d6fec1 phase-36: T7 sweep s3b — the constant-holder draw re-run: 1 of 80 (6 bodies), BUDGET 59 of 80
search: 1 of 80 exemplars matched lever-free in 0.89 h (6 of 486 bodies behind them; 28,042 compiles) — BUDGET 59 · NO-MATCH 18 · UNSTRIPPABLE 2 · MATCH 1

- func_801621CC by R6 inline lo + R7 do-while; delever --propagate: 5 of 5 sibling(s) banked, 0 refused.
- the figure that prices the draw is BUDGET 59 of 80: three quarters of the remaining bodies exhausted 400 compiles rather
  than being refuted, so this family is sampled, not measured. s3 had already taken its cheap half (10 bodies).
- two UNSTRIPPABLE recorded by name: func_8017DC80 (a launder with 2 outputs), func_80181A4C (instruction lw has no C
  spelling in the table).
- check-all: 218 passed, 0 failed of 218
  lever_census --check: 29,527 pin/asm sites, 29,527 marked !FAKE, 0 UNMARKED — OK
- snapshot row 14. Loop economics two agents in (R41): 30,358 -> 29,527 sites, 9,747 -> 9,320 bodies; the agents' own two
  bodies account for 255 of that and their toolified moves for the other 576, at zero drafting tokens.
2026-09-10 03:44:53 -06:00
Drew T 5603a114c2 phase-36: T7 sweeps s2/s3 — the constant-holder census corrected (537 of 17,302, not 284 of 10,958) and 10 bodies closed; the propagate namespace bug fixed
- s2 (the head, with R16/R17 added): search: 0 of 140 exemplars matched lever-free in 0.24 h (0 of 7,085 bodies behind
  them; 23,689 compiles). The two new generators closed nothing on the head; recorded as measured.
- agent a2's "284 constant-holder pins of 10,958" verified against the source rather than believed (R14), and my first
  instrument was wrong (R40): asking R16 directly answered 33, because R16 only fires on a split declaration while most
  pins carry their value as an initialiser. R3 converts one form to the other, so the reachable family is R3+R16.
  Corrected, both figures derived: 537 constant-holder pin sites of 17,302, in 510 bodies (152 initialiser, 385 separate
  assignment; by register $2 282, $20 136, $3 28).
- s3 drew exactly those 99 function names and closed 10 bodies before crashing with
  AttributeError: 'Namespace' object has no attribute 'allow_residue'
  in propagate — the a2 fix read the flag off the caller's namespace and the search engine builds its own Namespace for
  that in-process call. Fixed with getattr(a, "allow_residue", False): a library must not assume its caller's namespace
  shape (R43).
- the ten banks were real, proven by gating the tree the crash left:
  check-all: 218 passed, 0 failed of 218
  lever_census --check: 29,533 pin/asm sites, 29,533 marked !FAKE, 0 UNMARKED — OK
- by first move the ten are R15 x3, R6 x4, R7 x2, R9 x1 — the draw was right about the family even though R16 did not fire.
- snapshot row 13; s3 re-runs from the top with the fix.
2026-09-10 02:49:05 -06:00
Drew T 975850ff84 phase-36: T7 toolify a2 — generators R16 (constant holder inlined) and R17 (constant-run split), the directed form of a move R9 reached only by luck
- R16 writes a local whose only assignment is one integer literal at every use and deletes it. R6 stops at a temp read
  exactly once, so a holder read four times was invisible to the search and its whole family with it. Deleting it is
  byte-neutral alone but removes a quantity from the block, which is what lets the next move reach the allocator.
- R17 splits a run of consecutive same-literal assignments by moving the nearest differently-valued one into it, at each
  interior split point. find_free_reg's live-range scan (local-alloc.c:2109-2110): while the two constants' ranges are
  disjoint they share a caller-saved register; splitting makes the first live across the second and it takes another colour.
- known-true check: on the seed that keeps func_80168828's semantically-forced $4 pin, R16 then R17 reaches
  score 0 (OTHER; mine 108 ins, target 108) — MATCH at three of the six offered split points, in ten compiles where the
  blind search needed 2,271.
- the engine selftest's caller-saved assertion is now the ordering invariant (every targeted lever before every blind
  family) rather than a fixed window widened once per new generator.
- delever --selftest OK (4 new controls); delever_search --selftest OK; tool_census --check OK; SETUP row (R21).
2026-09-10 01:27:20 -06:00
Drew T 9c5ca46a2a phase-36: T7 agent a2 — func_80168828 at score 0 with the constant-holder pin deleted (125 bodies; 29,697 → 29,572 sites, R22 218/218)
- two moves: delete `register s32 c40 __asm__("$3")` and its `c40 = 0x40;`, writing the literal at its four uses (byte-neutral
  on its own — the pin was never doing the work); then swap the adjacent `f1e = 0x40;` and `f1a = 0x10;` so the 0x10 store
  splits the run of 0x40 stores.
- the residual reads like cse/sched and the decision is local-alloc's. Dumps of the real TU in both orderings differ on one
  .lreg line — `Register 76 used 5 times across 10 insns` -> `across 14 insns`, `Register 76 in 2.` -> `in 3.` — which is
  find_free_reg's live-range scan at local-alloc.c:2109-2110: unswapped the two constants' ranges are disjoint and share $v0,
  swapped they overlap and the first takes $v1.
- the $4 pin STAYS, and not as a lever: src/shared/ov/func_801687CC.h declares extern void func_80168828(void), so the
  target's `move s1,a0` has no C source. An uninitialised local, a pointer-typed one, a split declaration and deleting it
  outright all give the identical score-25 residual; both parameter forms are hard cc1 errors against that header. This is
  the first measured pin that only a declaration fix can remove — one of the 51 conflicts P35 ledgered for the types phase.
  The engine's score-1 text is a coincidence (its andi truncates garbage in $s1 and never reads $a0); not proposed.
- instrument fixed in the same change: --propagate refused all 124 siblings because the reshape deliberately keeps a lever.
  The allowance is now derived from the exemplar's own banked text (its surviving !FAKE markers), and a sibling whose remap
  would carry more levers than the exemplar is refused by name.
  delever --propagate: 124 of 124 sibling(s) banked, 0 refused
- check-all: 218 passed, 0 failed of 218
  lever_census --check: 29,572 pin/asm sites, 29,572 marked !FAKE, 0 UNMARKED — OK
- snapshot row 12; delever --selftest OK. The toolify (R16, the constant-run split) follows.
2026-09-10 01:23:22 -06:00
Drew T c00ffe5d44 phase-36: T7 sweep s1 — the R15 sink closes 6 more exemplars for free (267 bodies, 4 compiles each; 30,098 → 29,697 sites, R22 218/218)
The harvest half of agent a1 paying off. With R15 in the registry the engine was swept over the rest of the residue head
(--only the 56 other head functions, which draws every body of those names: 147 exemplars judged).

  search: 6 of 147 exemplars matched lever-free in 0.28 h (267 of 7,477 bodies behind them; 23,892 compiles) — NO-MATCH 141 · MATCH 6

- all six closes are R15, each in FOUR compiles: func_8013EB7C (126 + 7 copies) and func_8016DF5C (127 + 4 + 2 + 1) across
  their fleet copies. Every propagation 0 refused. R15 also moved func_80136824 from 21 to 2 as a first move.
- the loop's economics with denominators (R41): one agent's reading (~221k tokens) bought 130 bodies directly and 267 more
  for zero tokens — 397 bodies, 30,358 -> 29,697 sites (-661).
- check-all: 218 passed, 0 failed of 218
  lever_census --check: 29,697 pin/asm sites, 29,697 marked !FAKE, 0 UNMARKED — OK
- snapshot row 11 (9,617 -> 9,350 bodies); the checkpoint headline and loop state refreshed (R101).
2026-09-10 01:04:42 -06:00
Drew T 861dd0651c phase-36: T7 toolify a1 — generator R15, the sink (agent a1's crack made mechanical; reproduces it from the pre-bank text at score 0)
The harvest half of the one-at-a-time loop (R16): agent a1's reading of func_80156044 is now a move the engine can make
on any body, so the remaining head classes get it for free.

- R15 sinks the statement AFTER an if/else chain into every arm and deletes the variables it consumed:
  `if (c) { v = e1; } else { v = e2; } w = f(v);` -> `if (c) { w = f(e1); } else { w = f(e2); }`.
- it is a REGISTER move, not a scheduling one. A value set in every arm and read after the merge is a cross-block pseudo
  local-alloc never gives a quantity (local-alloc.c:472, next_qty reset at :517), so the arm holds two quantities and
  takes block_alloc's unrolled case 2 (:1499-1502, qty_compare :1578-1596). Sinking makes it a third block-local
  quantity, and case 3 (:1491-1496) falls through into case 2 and applies that comparison a second time, undoing its own
  exchange — the two caller-saved colours swap. It also takes the value out of global.c, where set_preference
  (global.c:1535+) had given it a copy preference through the merge result's argument copy.
- applicability is checked, never assumed: each consumed variable must be assigned exactly once in every arm by a simple
  statement, appear in the merge statement, and occur nowhere else in the function.
- if_chains() counts a line's CLOSING braces before its opening ones. On a `} else if (...) {` line the two net to zero
  and the first version's depth counter never closed the arm — the generator found 0 candidates on the very body it was
  written from. Caught by running it on that known-true case before believing it.
- ranked third in REG-caller / REG-mixed / COUNT; the engine selftest's "R5 in the first three" assertion widened to
  "R5 and R15 in the first four" rather than de-ranking the new move.
- verified: delever --selftest OK (3 new controls: a variable read after the merge, a variable one arm does not set, the
  brace walk's three arms); delever_search --selftest OK; and the known-true check — R15 run on func_80156044's
  pre-bank text emits the agent's crack and `--try` scores it
  `score 0 (OTHER; mine 74 ins, target 74) — MATCH`.
- SETUP row rewritten (R21), kit corpus regenerated, tool_census --check OK (371 copies + 30 pointers, 0 gaps).
- no src/ change in this commit; the sweep of the other 56 head classes follows.
2026-09-10 00:45:15 -06:00
Drew T fd2433b6d2 phase-36: T7 agent a1 — func_80156044 closed at score 0 by DELETING two locals (130 bodies banked, 30,358 → 30,098 sites, R22 218/218)
The first agent of the one-at-a-time T7 loop, on the rank-1 head class (130 copies, two NEEDED pins $2/$3). Six mechanical
rung-G runs had been stuck at best 1 on this body; the agent closed it at 0.

- the move is not a dial: the iVar3/puVar2 pair that every arm of the if/else chain set is deleted, and each arm gets the
  whole address expression (puVar4 = &D_80192454 + (((u32)param_2) & 0xffff) * 0x14). Two locals fewer than the levered
  text — shorter AND byte-identical, which is what this phase is for.
- mechanism, read from gcc 2.7.2's own source and confirmed in the .lreg/.greg dumps: scoping the base into the arm makes
  the block hold THREE local quantities instead of two, and block_alloc's unrolled case 3 (local-alloc.c:1491-1496) falls
  through into case 2 and applies qty_compare(0,1) a second time, undoing its own exchange — so the $2/$3 assignment flips
  (density formula local-alloc.c:1578-1596); deleting the cross-block variable also takes it out of global.c, where
  set_preference (global.c:1535+) had given it a copy preference for $5 through puVar4's argument copy, merged by
  expand_preferences (global.c:781-825) and overriding first-fit at global.c:1034-1067.
- why the engine could not find it: the u16-width move six runs found is a local optimum that IMITATES the fix by
  manufacturing the third quantity while paying an andi. No generator in the registry deletes a variable, so the search
  could not leave that basin. That is the toolify target and it follows in its own commit (R16).
- verified before banking (--try: score 0, mine 74 ins, target 74 — MATCH), then
  delever --apply-body: ... IDENTICAL on 1 object(s) (0.11 s) — KEPT, ledgered (rung E, a1)
  delever --propagate: 129 of 129 sibling(s) banked, 0 refused
  check-all: 218 passed, 0 failed of 218
  lever_census --check: 30,098 pin/asm sites, 30,098 marked !FAKE, 0 UNMARKED — OK
  audit_public: OK — 0 offenders among 11445 tracked paths
- snapshot row 10; the agent's body.c and mechanism.md kept in the pack as the reading behind the generator.
2026-09-10 00:39:14 -06:00
Drew T 5a8bd10217 phase-36: decision log P36 S101 — from search to reading (the scored engine, the head as the number, one agent at a time) 2026-09-09 23:33:36 -06:00
Drew T 7b2200edad phase-36: the tail pass g6 + g6b (47 + 63 of 400 small classes; 186/191 siblings propagated), R22 218/218; 30,806 → 30,358 sites; --try (a candidate scored without a tree write), delever_pack.py (the 57 T7 packs + PROMPT.md), --restore refuses an empty snapshot; the checkpoint: T7 as one agent at a time, approved, starts in the fresh session 2026-09-09 23:32:57 -06:00
Drew T 2f3ce92a15 phase-36: rung G run g5 — the head re-drawn wide: 5 of 70 (small classes, 62 bodies), R22 218/218; 30,892 → 30,806 sites; the wide-search lever is spent on the big classes (112,216 compiles); R14 rewrites prototypes, R8 names repeated operands/groups, R12 splits multi-declarator lines; C/D-only bodies are done and not drawn, the seed keeps class C/D sites 2026-09-09 22:07:17 -06:00
Drew T 1ec67f6677 phase-36: rung G run g4s — func_8016E9EC's shape closed in three classes (133 bodies, R22 218/218; 31,025 → 30,892 sites); generators R12 widths (u8/short/int), R14 parameter width, R8 shared base, R10 cast alias; the bank and propagation in process (apply_body_core); the per-tag scratch-object race fixed; propagate's empty-list return 2026-09-09 20:18:43 -06:00
Drew T 068781ae0b phase-36: rung G run g3 — 13 of 64 classes closed (R12 width ×5, R7 ×3, R9 ×3, R10 ×2 — lane B's width and parameter moves half the closes), 1,516 bodies banked + propagated 1,503/1,503, R22 218/218; 33,031 → 31,025 sites; the S101 checkpoint block written 2026-09-09 19:55:37 -06:00
Drew T 5ae0b5cebd phase-36: rung G run g2 — func_80142EC0 closed (do-while + swap, 132 bodies banked, propagated 131/131), R22 218/218; 33,295 → 33,031 sites; the wider beam with R10/R12/R13/R8-cse moved nine of fifteen past g1; cookbook §455; lane B's constant-swap and do-while claims verified on bytes (the ledger in residual_moves.md) 2026-09-09 18:51:01 -06:00
Drew T a4cbe0d5a3 phase-36: rung G run g1 — 1 of 16 exemplars (func_801424E4, the count-changing body rung D left at 2) closed by three composed moves, 132 bodies banked + propagated 131/131, R22 218/218; 33,427 → 33,295 sites; R5 skips constant operands (lane B's fold claim verified on bytes); bottom-up order within a file 2026-09-09 18:22:01 -06:00
Drew T 623e553408 phase-36: rung G — tools/delever_search.py, the guided search (the score is the oracle's own object read as an edit distance, the residual classified to pick the move families, a beam composing 2–3 moves; positive controls 1–2 PASS, 3 FAIL on a missing inverse); R8/R9 + the unwrap in delever's generator registry; the 301-row ledger hash defect fixed at its cause and repaired; lane B's residual→move map banked 2026-09-09 18:11:16 -06:00
Drew T 7192ab9ab1 phase-36: the S100 checkpoint — the triage Drew approved, the compute-only guided-search engine (rung R is blind: it tests for IDENTICAL and throws the distance away), my recommendation on Fable's role, and the LoRA parked for the endgame 2026-09-09 16:19:17 -06:00
Drew T 72a9ab1129 phase-36: the free-bank sweep measured — rung R is replication, not discovery (0 of 300 at cap 40 AND at cap 400; the cap was never binding at ~57 candidates/body; the instrument cleared by hand) 2026-09-09 16:10:11 -06:00
Drew T aef1159488 phase-36: T6 CLOSE — both yield lines measured (permuter 5 of 16 exemplars / 665 of 2,131 bodies; recipes 134 of 134 in 6.0 min), 664 sites gone (34,091 -> 33,427), R22 218/218 at every step; the S99 checkpoint written for T7 (which starts only on Drew's direct approval) with the parallelised rung-R sweep as the drawable work meanwhile 2026-09-09 13:02:51 -06:00
Drew T 1c23550540 src(phase-36): T6 propagation p1 — the four classes rung D cracked, spread to 525 siblings (R22 218/218)
- delever --propagate: 132 + 130 + 131 + 132 siblings banked, 0 refused; each sibling's body is the exemplar's reshaped
  text with ITS OWN func_/D_ addresses (the class is "identical modulo addresses", so the two old bodies' tokens
  correspond one for one), judged on its own objects before it is kept
- the class key comes from the FIRST bank in a body's chain, not the last: a body that was reshaped and then tidied has
  two rows, and the later row's before-hash describes a text only that body ever had (func_80163EC8 found 0 siblings
  until this was fixed, then 132)
- R22 clean fleet: `check-all: 218 passed, 0 failed of 218`
- lever_census --check: 33,427 pin/asm sites, 33,427 marked, 0 UNMARKED — 664 sites gone this session (34,091 at S99's
  open); lever_progress snapshot "T6 p1"
2026-09-09 13:00:19 -06:00
Drew T a2da99b130 src(phase-36): T6 rung D banked — the four exemplars the permuter closed, tidied and byte-judged (R22 218/218)
- delever_permute --bank: 4 winners applied through delever --apply-body, each IDENTICAL on its own object; the winner is
  now TIDIED first (pycparser reprints a body it parsed: two-space indent and a corpse `;` where a statement was inlined
  away) and the tidy is judged like any other candidate, so the source keeps the tree's shape; parenthesisation and brace
  style are deliberately left to the formatting phase, over the whole tree at once
- a slip, named: --bank re-applied a permuter body over the ONE-LINE version rung R had already banked for
  func_80135D20; the clean text was restored through the oracle (label d1fix) and --bank now skips any body the ledger
  already calls LEVER-FREE
- --recipes is killable now: the oracle writes the candidate into the tree to compile it, so the original goes into
  inflight.json first (P35's rule: a tool restores from its own snapshot) — a killed run had left a candidate in src/
- rung R's R6 generalised from "assigned once, read once" to "dead after one read" (the lever rung D actually found:
  uVar5 is assigned in two branches and only one was inlined); it still does not reproduce that class's win, which is
  recorded as an open item rather than papered over
- lever_census: 33,953 sites (was 33,957), 0 UNMARKED; lever_progress snapshot "T6 d1"; R22 218 passed, 0 failed of 218
2026-09-09 12:21:42 -06:00
Drew T 8fac96651f docs(phase-36): the lever series as a tracked deliverable — docs/levers.md + tools/lever_progress.py (Drew's directive)
The pin/hint removal's COUNT OVER TIME is a deliverable in its own right: the post-100% chart, the story's spine, a wiki
page, and the day-one rule the decomp-architect kit should carry. It is only ever counted by the phase that removes it, so
it has to be captured while the work happens — a census is a moment.

- docs/levers.md: the taxonomy (A pins · B1-B4 barriers/launders/keep-alives/hand-placed instructions · B5 GTE, not a
  lever · C volatile · D bare register · E asm-label aliases · F builtins · G attributes); a GENERATED §2; how the levers
  got in phase by phase (P18's pin toolkit took the wave close-rate 33% -> 56% -> 90%; the family engine then copied every
  lever across up to 134 overlays, which is why 1,758 distinct bodies are 12,578); the ladder with each rung's measured
  yield; §5 the prevent-vs-defer argument; §6 what the wiki, the kit and the story each take.
- tools/lever_progress.py: --snapshot appends a milestone row (the census's totals by class + HEAD) to
  docs/lever-progress.tsv and re-renders the document; the campaign table is derived from the de-lever ledger on every
  render and scored as state TRANSITIONS, so the rung that FINISHES a body gets the credit (counting first-rows-only
  reported rung R's 134-body batch as zero); --check refuses a series that is not this tree's.
- the numbers, generated: 21,061 sites removed or rewritten across 17,119 bodies against 33,957 still standing — 38% of
  the class A/B population came off with no understanding at all, which is the evidence behind §5's rule:
  BAN THE SILENCE, NOT THE LEVER (a lever is allowed and is a marked, ledgered, published debt from the first bank, with a
  one-compile bank-time trial; never block the byte gate on it).
- Reference-index row (doc_links OK), SETUP row, tool dictionary row, CURRENT_PHASE entry for the story.
2026-09-09 12:10:24 -06:00
Drew T 1761a31256 docs(phase-36): accelerators P36 S99 — the positive control on a search scorer, a target built by the candidates' own toolchain, a generated artifact nothing consumed, steering by the residual, and same-day toolification of a search win 2026-09-09 11:28:52 -06:00
Drew T 47e53142f7 docs(phase-36): cookbook §454 — rung D and rung R: the target that was assembled from a listing (a base score of 28 for a byte-identical body), the positive control that names it, the profile following the register, the two wins turned into recipes R5-R7, propagation by address remap, and the starting-distance split of the population 2026-09-09 11:24:31 -06:00
Drew T c0e8fbdaae phase-36: T6 — the rung-D instrument fixed (the target was assembled from a listing), rung R built (R2/R3/R4/R5)
THE INSTRUMENT (R40). Two campaigns returned "0 of 16" with a straight face; both were the harness. The target object had
been assembled from a DISASSEMBLY LISTING, which is a second toolchain with its own answers:
  - objdump prints the pseudo-instruction `move` for `addu rX,rY,$zero`; gas assembles `move` as `or` — 24 wrong words in
    one 234-instruction function, silently;
  - a listing's %hi/%lo pairs come back RESOLVED with no relocation, while every candidate carries one, and the masked
    scorer compares reloc operands.
The permuter therefore scored 28 for a body that IS byte-identical: score 0 was unreachable and every NO-MATCH was its own.
  - tools/delever_permute.py: the target is now the tree's OWN (levered) body compiled by the build's tail into a
    one-function object — the candidates' relocations by construction — and `match_one` must call that body a MATCH against
    the ROM listing before the search starts (R34 keeps it from being circular). Base score for the tree's own body: 0.
  - tools/p16_permute.py `setup(target_o=)` + tools/permuter_ils.py `--target-o` (defaults unchanged).
  - `--positive-control TU FN`: perturb a matching body by one commutative swap, require the permuter back to 0.
  - tools/verbatim_target_s.py --gas now VERIFIES itself: assemble, disassemble, compare word by word with the image,
    `.word 0x…`-patch what does not reproduce (24 in that function), REFUSE what still disagrees. The listing is a public
    artifact (decomp.me) and was wrong for every function containing a `move`.

THE PROFILE. The weight profile now comes from the register a needed pin names, not just the site kind: callee-saved
($16-$23) is an allocation-order residual -> regalloc; caller-saved ($2/$3/$4-$7) is not -> cse. Read from the bytes: the
residual on func_80163EC8 (`register … __asm__("$2")`) is `and v0,v1,v0` against `and v0,v0,v1` — the operand order of one
`&` — and the regalloc profile weights perm_commutative 2.0 while cse weights it 40.0.

RUNG R (tools/delever.py --recipes): the cookbook's byte-neutral shape recipes, mechanically, seeded with the body's
lever-free text — R2 the formerly-pinned declarations permuted, R4 one moved through the whole declaration run, R3 an
initializer split placed after the run (C89), R5 the operand order of one commutative operator (the caller-saved lever, and
the only recipe needing no pinned declaration). Identity control on both the splice and the oracle before any verdict;
markers scrubbed within the banked body's own span only; selftest cases on a fixture whose answers are known by hand.

Also: a threading race in the site cache published the empty dict before filling it and made a whole batch report
"no site in this TU"; the file-scope asm dropper took an asm-LABEL clause for a statement. SETUP + dictionary rows.
2026-09-09 11:08:20 -06:00
Drew T 22a31bc025 phase-36: T6 — the kit corpus and the tool index regenerated for delever_permute.py (tool_census --check: 0 gaps) 2026-09-09 10:23:35 -06:00
Drew T 6e1677b4da phase-36: T6 rung D built and calibrated — tools/delever_permute.py, the GTE levers on the ladder (462/462), four harness defects
- tools/delever_permute.py: one exemplar per RESIDUE text class from the ledger (copies desc, needed asc) prepared as a
  single-function TU (delever's rung-A rewrite; other definitions -> prototypes; shared-header includes -> their prototypes;
  INCLUDE_ASM and file-scope asm dropped; the build's own CPPFLAGS through cpp -P), the target regenerated from the ROM image in
  BOTH forms (--gas for target.o, splat for match_one), permuter_ils with the profile from the NEEDED kinds, a winner banked only
  through delever --apply-body + the GTE re-fold. Scratch/winners keyed alias+fn (R48).
- the control (R39/R56, new): every attempt first requires the LEVERED body to be match_one MATCH against the regenerated target,
  then records the lever-free body's distance. --calibrate --limit 12: 12 of 12 MATCH; starting distance min 8 / median 78 / max 276.
- delever: ("B","gte-lever") joins REMOVABLE — a direct statement's clobbers reset to its canonical set, a variant-macro use pointed
  at the canonical macro whose name comes from the variant definition's SIGNATURE (gte_rt_m -> gte_rtv0tr, not Sony's gte_rt);
  462 of 462 gte-lever sites now offered to the ladder, 0 before. gte_consolidate.canonical_match() is the one reader of the
  canonical table (R33), direct_rewrite refactored onto it; both selftests green.
- p16_permute.setup(outdir=) + permuter_ils --pd: a scratch dir keyed by the caller, defaults unchanged.
- four harness defects found by running it: the splat listing is not assemblable (R98 in a second place); pycparser rejects
  __attribute__ and the permuter then silently permutes nothing; include_asm.h injects a file-scope .include "labels.inc" that
  collides with the permuter's own macro.inc; an asm-LABEL clause is not an asm statement (a bare scan ate one and left a headless
  K&R body). SETUP row (R21), dictionary row (R87), .gitignore allowlist for the outcomes ledger.
2026-09-09 10:21:16 -06:00
Drew T d025e67e71 phase-36: T5 CLOSE — the GTE consolidation and the dead-macro sweep: include/gte_inline.h (50 canonical macros for 9,102 definitions), 8,951 per-TU definitions deleted, 629 clobber variants freed byte-identical and 70 kept as marked levers, 575 direct statements → Sony-named calls, 274 dead launder macros swept; the census learns cross-file macro names (10 launders surfaced in two shared headers, 6 removed); per-TU asm macro definitions 9,540 → 314 with 0 canonical duplicates; THE NUMBER 34,091 sites (incl. 462 GTE levers) in 12,712 bodies, all marked, 0 orphans — lever_census --check OK; R22 218/218; SETUP rows; kit corpus; the 🛑 block for T6 2026-09-09 07:12:06 -06:00
Drew T 5b6e1a2fe7 phase-36: T5 — the consolidation applied (644 files: 8,951 per-TU GTE definitions gone, 629 clobber variants byte-identical without the clobber, 70 kept as marked levers, 575 direct statements → canonical calls, 85 header-bound homonyms kept) + the marker repair (scrub 344 misplaced, re-mark 349); four instrument fixes: scoped renames, header-bound homonyms kept, object-like macros, the canonical table stable (the header's definitions in the inventory) and the census cache keyed on the tables; R22 218/218; the number 34,090 (33,625 + 465 GTE levers) all marked, 0 orphans, --check OK; kit corpus; log entry 2026-09-09 06:29:00 -06:00
Drew T 0bd784c64e phase-36: T5 (header step) — the GTE consolidation: tools/gte_consolidate.py (signatures by the build's own maspsx→as tail: bytes + operand counts + clobbers; one canonical text per signature under Sony's names, Sony's clobbers canonical even when every definition carries the steer; lever variants <name>_m tried as canonical first; direct statements → canonical calls; --sweep), include/gte_inline.h (50 macros for 9,102 definitions) included from common.h — R22 218/218; the census's gte-lever class + per-TU definition count + strict gate; the cycle's MODE=gte; dictionary + SETUP rows; kit corpus; log entry 2026-09-09 05:28:50 -06:00
Drew T 917c68afd9 phase-36: T4 CLOSE — the mechanical campaign over the whole population: 16,334 bodies judged in 13 gated batches (3,341 lever-free = 20.5 %; 21,063 of 56,445 sites removed or rewritten = 37.3 %; 8,239 replays, 1 disagreement; 49,487 compiles); the file-scope asm statements judged too (batch tus11: 6 barriers NEEDED, 7 .section blocks refused as asm-data and marked); THE NUMBER 53,234 → 33,625 sites (−36.8 %) in 12,501 bodies (1,728 distinct), 33,625 marked, 0 UNMARKED, 0 orphans — lever_census --check OK; the residue 12,967 bodies in 1,803 distinct classes (pins-only 6,018 · pins+asm 4,310 · asm-only 2,141 · C/D-only 498); published by make report (README line 30, progress.json counts.levers, the timeline); kit corpus; the 🛑 block rewritten for T5 2026-09-09 05:05:33 -06:00
Drew T 77a1298cb7 phase-36: T4 — batch tus3 killed mid-apply by the harness's low-memory guard (22 GB free): recovered by dropping its 641 ledger rows (backup) and --restore (50 files, src clean); --restore now drops the in-flight label's rows itself (inflight.json carries the label); the cycle's usage: run it DETACHED (setsid nohup) with a tiny waiter; SETUP row; kit corpus; log entry 2026-09-09 03:35:35 -06:00
Drew T dd01cbdf6e phase-36: T4 (tool fixes between batches) — 'done' is per body (tu, fn, after-hash): keying it by text alone let every fleet-wide copy of an all-NEEDED exemplar pass as done unmarked (2204 → 2483 drawable files); the includer map cached per file (29 s → 1.3 s per batch, equal to the uncached map); the cycle waits out a transient .git/index.lock and clears a stale one (batch tus2's commit was lost to one and committed by hand, 85905840c); kit corpus; the log entry with tus1/tus2 — the number 46,424 sites in 14,758 bodies · marked 9,393 · unmarked 37,031 2026-09-09 03:30:53 -06:00
Drew T e5f59c12f4 phase-36: T3 close — the campaign tool proven end to end on ov_SC04_011 (batches t3_tus1 + t3_tus2, R22 218/218 each): the zero-register use composed into its host edit (the one refused body redrawn via --redraw), a removed site consumes its trailing !FAKE marker, the census counts ORPHAN markers (--check fails on them; the walk cache keyed on the tool's hash — it had hidden them) and delever --scrub removes them (2 scrubbed here, object identical, R22 218/218 wall 143 s); the cycle's greps fixed (no ^ anchor, an empty verify line refuses, THE PHASE'S NUMBER line, entries before the checkpoint block); the number 53,033 sites / 15,638 bodies (2,246 distinct) · 310 marked · 0 orphans; SETUP + dictionary rows; kit corpus; the t3_tus1 entry rewritten from the logs (R66); the 🛑 block rewritten for T4 2026-09-09 03:14:30 -06:00
Drew T 39e3e1851f phase-36: T3 (tools) — tools/delever.py the campaign tool: --plan/--apply (the file is the write unit, its final compile through every recipe the proof; 'done' = a ledger fact keyed by the body's normalized text before/after; replay from an exemplar in one compile; !FAKE markers on class A/B survivors; --restore from inflight.json; --apply-body for T6/T7; a selftest with a stub oracle), the launder-ASSIGNMENT rewrite (989 of 4,793 direct launders — deleting them made cc1 2.7.2 abort: the probe's 'Done' error, reproduced 3/3), macro shapes (SHB deleted, a launder expression valued, compound macros refused for T5), the oracle's COMPILE-CRASH verdict + judge_all + the mtime restore, the census's src_stamp/head, tools/delever_cycle.sh (apply → R22 → census → log + headline → commit); selftest OK; census 53,234 unchanged; calibration 177/177; plan ov_SC04_011 = 18 files / 176 bodies / 540 sites; SETUP + dictionary rows; kit corpus; T7 waves need Drew's direct approval (decisions) 2026-09-09 02:45:58 -06:00
Drew T 617f29e30c phase-36: T2 — the oracle and the probe: tools/delever_oracle.py (4,284 recipes via make -n -W; a candidate compiled in place to a scratch object and compared with the fleet run's; calibrated 177/177 untouched + twin 32/32 + positive control DIFFERS) and tools/delever.py (positional rewrites per lever class, rung A strip-all + rung B greedy, headers serial after the TU phase); --probe on 283 distinct bodies: A identical 53/283, sites removed 561/1,309 (42.9 %), needed 748 (launder 77 %, barrier 82 %, pins 45 % — v0/v1 + a0–a3 dominant), 0.225 s per compile — T4 priced at ~94k compiles ≈ 0.5 h, the residue ≈ 81 % of bodies ≈ 1,800 distinct exemplars; dictionary + SETUP rows; kit corpus; the 🛑 block for T3 2026-09-09 02:03:04 -06:00
Drew T a1407bdfc1 phase-36: T1b — the verbatim manifest learns the in-function form (49 rows: 27 PERMANENT hand asm incl. 22 per-overlay scratchpad stack-switch trampolines, 8 Sony GsTMDfast* routines carried as asm, 11 DECOMPILE-NOW + 3 UNCERTAIN game bodies never decompiled); verbatim_check detects the form structurally via lever_census.whole_body_asm_functions (--strict: 2,709 bodies, no drift); the census defers exclusion to the manifest's dispositions — the phase's number 53,234 sites in 15,679 bodies (2,227 distinct); progress.py counts PERMANENT (27) + SDK (8) with a dated correction; README/wiki/verification/gen3 docs corrected (14 game functions were asm in C shells); kit corpus 2026-09-09 01:44:31 -06:00
Drew T 357f8a1ed3 phase-36: T1 — tools/lever_census.py, the self-asserting lever census (coverage asm 80,396 = 66,415 live + 7,189 macro-block + 6,792 comment/dead; 4/4 controls; the five manifest bodies excluded): 53,221 pin/asm sites in 15,666 bodies (2,214 distinct) — 37,720 register pins + 15,501 asm statements, 0 marked; 6,911 GTE ops and 23 whole-body asm routines in C shells (2,683 sites, outside the manifest — Drew's call) set apart; progress.py levers block + README sentence; dictionary + SETUP rows; kit corpus; the 🛑 block for T2 2026-09-09 00:52:22 -06:00
Drew T e6d98dd1d4 chore(phase-35): CLOSE — Gen3's dedup phase: one source per unique function (3,175 shared headers, 3,173 registry groups incl. the h_text tier, the macro header gone, the five twins from one directory, S1 a tools-health gate with a second oracle, 14 macro-era tools frozen and 4 retired behind a guard, the published counts corrected) — v2.1.0
- PhaseEnd_Phase35.md written; CURRENT_PHASE.md archived to phase-ends/logs/Phase35.md (R19); DIGEST §0/§2 appended (step 3b)
- T0–T8 + T5b across S94–S96 (S94 died at 91 % without a checkpoint; S95 recovered it from the transcript; S96 finished)
- close: R22 clean fleet 218/218; tools-health OK (S1 10,180/10,180, 0 violations; dedup-check 3173/0; the guard 0)
- rules: R96–R99 ratified at gate 1; candidates (a)–(g) proposed for Phase 36 gate 1
- v2.0.0 -> v2.1.0
2026-09-08 23:19:40 -06:00
Drew T ce837b1e46 docs(phase-35): T8 — the record: The-dedup-engine.md rewritten for the shared-source model (the shape, the h_exact/h_text/h_norm tiers, share_body and its four first-day defects, the S1 gate and the second oracle, the numbers as a dated derivation); Repository-layout, Where-the-project-goes-next, Verification-and-progress, how-to ch.10, README prose, gen3-standards (§4 row struck, DoD item met), gen3-handoff (dated snapshots); cookbook §453 + a retirement banner on §14, the index regenerated; decision-log P35 (R31), accelerators P35, DIGEST §4; doc_links strict 0 broken, wiki 32/32, kit coverage OK, kit corpus 2026-09-08 22:52:09 -06:00
Drew T e7b0cfb626 docs(phase-35): T5b verify — tools-health OK with the text tier in every rung (S1 10,180/10,180, dedup-check 3173/0, the guard 0); the timeline regenerated 2026-09-08 22:47:26 -06:00
Drew T ac8c29edb1 src(phase-35): T5b — the text tier: 38 same-address functions whose bytes vary per binary (the TU's declaration environment carries the original per-overlay variance) share one text each through h_text registry groups with per-member h_exact — 1,957 private copies in 1,540 TUs replaced by the include, 38 headers (func_<VRAM>__t<hash8>.h), 138/138 binaries green per binary, 0 rejected; dedup_integrate C1 per member (3173 validated, 0 failed); share_census indexes h_text groups by site, exports text classes, the S1 text half is a violation (0 now), the census json carries the oracle's counts; share_body --bucket text; progress.py/README: 103,015 bodies written once, 38 text-tier functions / 2,030 sites, 1,668 copies of 381 tiny bodies deferred; R22 clean fleet 218/218 in 90 s; SETUP; kit corpus 2026-09-08 22:39:42 -06:00
Drew T c8224e657f tools(phase-35): T7 — the S1 invariant wired into tools-health (share_census --selftest + --check --strict-macros --strict-text, by exit code), C2c/C2d in dedup_integrate --check (one source under src/shared/ defining one function; every member's site includes it — from the census's per-instance forms), progress.py: unique_function_bodies 105,007 / duplicate_source_copies 160 in 51 ledgered classes + the dated corrections list + the README sentence; the second oracle refined (distinct TUs; deferred vs pending vs violation): 380 texts deferred inside cross-address classes, 38 same-address texts / 2,030 sites byte-variant per binary (PENDING the owner), 0 violations; negative control in place: one reverted include -> S1 FAIL naming the class + C2d naming the member; tools-health OK (551 s) 2026-09-08 21:46:05 -06:00
Drew T 93b4706c96 docs(phase-35): T6 CLOSE — tools-health OK with the macro-form guard (0 LIVE tools reference the retired form; 14 frozen, 38 retired); the timeline regenerated against the committed digest (74 rows); the wiki's dedup page repointed from the retired dedup_propagate to share_body (T8 rewrites it); the cycle driver's dictionary row without rule ids (the kit's leak check); the three red chain runs and their causes in the phase log 2026-09-08 21:16:02 -06:00
Drew T db63fcc673 tools(phase-35): T6 part 2 — the dead macro branches dropped from 12 live tools; the macro-form guard in tool_census --check (ast scan of every LIVE tool, FROZEN/retired/6 whitelisted detectors excluded; 0 LIVE tools reference the retired form; --guard-root negative control: the pre-T4 tree flags exactly the 12 fixed + 3 retired); progress.py: an empty-bodied included member is EMPTY, not folded into REAL (the R32 bucket assertion caught the double count) — the fleet denominator 363,221 -> 363,680 (+459: SC03_015's 219 single-site macros, SC03_118 +3, the never-extended members of five groups) and REAL 360,744 -> 350,533 with EMPTY up the same; progress.json + README block + fleet table regenerated; SETUP; kit corpus 2026-09-08 20:53:05 -06:00
Drew T 5a9f455e60 tools(phase-35): T6 part 1 — 14 macro-era tools FROZEN (tools/frozen.py: one refusal from main(), imports never exit; the plan's 7 + 7 the guard census found, family_remap's CLI among them), 4 retired to tools/sunset/ (dedup_propagate + dedup_extend -> share_body.py with add_members_surgical and the load_sig library moved verbatim; macro_draft; test_reconcile_ledger), six lane callers repointed to share_body --apply --bucket new, validate_targets imports share_body, tool_census accepts FROZEN; dictionary + sunset README rows; kit corpus 2026-09-08 20:34:41 -06:00
Drew T cd43347791 config(phase-35): T5 CLOSE — the registry behind the source repaired (639 including-but-unlisted members added to 5 groups, the 5 verbose groups converted to shorthand; add_members_surgical refuses a verbose group, R43); S1: 10,180 classes, 10,180 satisfied, 0 violations (share_census --check exit 0); same-vram backlog 1,099 -> 51 classes = the ledger (50 TU-CONFLICT + 1 GATE-REJECT); dedup-check 3135/0; audit-binaries OK; registry 2,220 -> 3,135 groups; the tail run (bucket new empty); cycle logs; SETUP (the context guard); kit corpus 2026-09-08 20:24:28 -06:00
Drew T e4b25e5f70 tools(phase-35): T5 — share_body_cycle.sh, the unattended batch cycle for bucket new (batch → exit code + gated N/N → phase-log entry → commit → clean fleet run every N batches, stops on the first red); share_body --label; dictionary row + SETUP; kit corpus 2026-09-08 19:53:09 -06:00
Drew T a60340c6d4 src(phase-35): T5 — E_func_80168B70 re-exemplared from the majority text (share_body.py --reexemplar: header ← ov_SC01_000's copy, 7/7 includers green first, then 134 private copies → the include in 129 TUs, 141/141 binaries green, 0 rejected; the minority-header ledger row dropped); bucket 0 closed: 183 classes → 135 fully shared, 48 ledgered TU-CONFLICT (late-overlay declaration conflicts, for the types phase); SETUP paragraph (--batches, snapshot restore, the cause rule, --repair-registry, --reexemplar); kit corpus 2026-09-08 19:41:40 -06:00
Drew T 0bccef9016 tools(phase-35): T5 — share_body.py, the permanent share tool for the include-at-site form (exemplar by majority text, header written once, private copies → include at their position, per-binary gate with object comparison and bisect, registry appended by text, exception ledger); the R37 probe: func_801681FC shared by ov_SC04_008 + ov_SC05_009 (2/2 binaries green, group S_func_801681FC); the census exports per-instance line ranges; bind_alias_header factored out of macro_to_header; SETUP + dictionary rows; kit corpus 2026-09-08 18:12:41 -06:00