- closes, each --try 0 then apply-body IDENTICAL + propagate N/N 0 refused: func_80133AB0 (u16 width moves), func_80130D48
(one call per goto-tail site), func_80135168 (reused temps split + H16 member store), func_80134A74 (widths + join
statement in both arms), func_80148AFC (implicit handler argument + later operand), func_8015D738 (jump threading:
re-read + a do-while on precedent, the class raised with Drew), func_80135004 (temp split + argument from its global)
- func_8017EEC0: the uninitialised a0v T4 tus10 left is the parameter (8/8, IDENTICAL)
- CI red since cb2fb5e6d: verbatim_check --strict saw the DECOMPILE-NOW row func_8017EEC0 converted; row removed (one
row), --update keeps order + UTF-8 (proven equal to the hand fix), verbatim_check --strict now in make tools-health
- delever.split_reused_locals = family R23 (selftest + two refusals; known-true: joint split = the agents' measured 12/26)
- check-all 218 passed 0 failed (twice); lever_census 20,206 marked 0 UNMARKED; Drew: at most five concurrent agents
tool_census's two enumerations disagreed on one file: the new tool was written but never added, so the dictionary row
existed for a path git did not carry. That is exactly the disagreement the second oracle is there to find.
Six T7 agents independently reached score 0 by restoring an argument the decompiled source had dropped, and no generator
could reach the class because every other family rewrites statements that exist while this changes a call's ARITY. R19
closes that gap without cracking anything: it finds every call whose in-scope declaration is narrower than the callee's
real definition, then offers one candidate per value already in scope (each parameter, each local declared before the
call) and lets the byte oracle pick. The missing argument is never inferred.
- known-true check: run on the pre-bank text of func_8017A3D8, which agent a12 solved by hand, R19 emits that agent's
exact fix and --try scores it 0 (OTHER; mine 53 ins, target 53) — MATCH.
- two spellings were wrong before that passed. It took the return type from the DEFINITION and produced
((void (*)(s32))f)(a) != 0, which cannot compile because the defining TU says void where this one says int — it now
repairs the arity only and keeps the TU's declared return type. And it required a simple statement, so it found
nothing on the very body it was written from: these calls live in and far more often
than in a plain statement.
- it also sees the cast-wrapped form ((s32 (*)(void))f)(), which is how m2c usually spells a dropped argument, and
replaces the whole wrapper rather than nesting a second cast.
- ranked FIRST in every residual class: it emits candidates only for calls whose declaration provably disagrees with the
definition, so it costs nothing when it does not apply. The engine selftest's ordering invariant is updated to say so
rather than being widened again.
- argcheck now carries each definition's return type, which the cast route needs.
- selftest: two positive assertions and two controls (the declared return type is kept; the definition's is refused; a
call inside a return statement is seen; a matching declaration offers nothing).
- a22: func_8017B238 closed by giving the if-arm's pointer and the else arm's first table address one function-scope
local. Three decisions turn on that edit, all dump-proven: make_regs_eqv's head rule (cse.c:840-857), set_preference
stripping one RTX level so an arithmetic set inherits its operand's register (global.c:1535), and combine_regs with
birthing_insn_p's reg_n_sets == 1 (local-alloc.c:1765-1788, sched.c:2469) — which is why the merge must be with the
else arm's non-call-crossing temp. 26,714 -> 26,462 sites.
- a14 reaches score 0 on func_80139BE0 but only by an INVENTED identically-zero term whose sole purpose is to keep a
value live. NOT BANKED: an invented no-op expression is a compiler-forcing construct in C clothing, and worse than the
marked launder it replaces because the launder is counted and this would be silent. The phase's own rule is ban the
silence, not the lever. Parked for the structs/types phase with its reading; the tree comment above it ('no pure-C
spelling survives that fold') is refuted.
- a6 corrects cookbook 455: cse1 (cse.c:7439-7502) rewrites the producer's destination to the copy's whenever the
producer is the immediately preceding insn; combine only finishes the job once that adjacency is broken. It enumerated
the three lever-free blockers can_combine_p admits and showed the body can pay for none, then scanned all 4,284 built
objects for the shape — 101 hits, every lever-free precedent paying with a genuine second use, a narrow local with two
consumers, or a join label.
- a24's residual was one absent load: cse forwards a just-stored halfword so no lh is emitted, and seven branch
displacement mismatches were downstream of it. Its method gap is the instrument to fix next — three agents have now
asked for local-alloc's quantity table in the pack, and alloc_table.py prints an empty or one-row table because it
keys on dump lines that are often absent.
- Drew's struct question answered on the record: structs are not in the binary (types are erased; no metadata in a
retail build), what is there is base + offset + width + stride, so a struct is an inference across every function
touching a base — which makes per-function struct invention the wrong unit and is the failure P35 already recorded.
Recommendation: keep pins as the main lane, build a zero-token struct evidence census beside it, park stuck pins with
their evidence, and fix call signatures first because they are the bigger and cheaper blocker (471 narrow call sites
in 323 pinned bodies). Measured: 372,224 raw cast dereferences against 92,624 struct member accesses.
- decomp-architect/corpus/record/: the how-to (13), decision-log, accelerators, retrospective, story, wave-playbook, effort-map,
gen3-standards, gen3-handoff, DIGEST and every PhaseEnd (34) verbatim behind an authored front page (what each is, how to
read it, what is NOT there — the phase logs, R19 — and that the mining pass is their distillation); tool_census: RECORD_SOURCES
+ record_dest + the third corpus in plan/write/check (358 copies + 28 pointers, --check OK); kit_lint exempts corpus/record;
SETUP Step 6 gains 2c docs/inherited-record.md (+ the verify line; expected-manifest +1); ops-setup/README/tree/methodology/
wiki page/Home/Tools page/README bullet/SETUP row: "two dictionaries" → three
- tools/kit_coverage.py (+ config/kit_coverage_map.tsv): derives R1..R83 from DIGEST §3 (asserted contiguous) and the 58
accelerator entries (headings + numbered items), asserts each is cited by a provenance line of the registry seed / the
kernels or dispositioned (G / DK / FOLDED:G / ENV / PA / SEED: / KIT: / RECORD / COOKBOOK / NOT-PORTABLE; unknown ids
refused); first run: 26 uncited rules + 21 uncited entries → DK-66 (a ledger's tie-break, a checker's widening and a blanket
commit are part of the instrument — R70/R80/R52), DK-67 (the ignore file's directory-form wall — S91 (1)), DK-68 (a
summarised signal is a claim, not ground truth — R14/R66) in a new kernels section 8 (the museum is 9; "In all" 68) + 41
dispositions (15 PA, 3 ENV, folds into G6/G18/G38/G66/DK-12/19/20/22/25/26/31/35/44/45/46/57/61, 1 KIT template, 1 COOKBOOK);
now 0 UNCOVERED on both populations; wired into tools-health after tool_census --check; SETUP row + dictionary row
- verify: tool_census --check OK; kit_coverage OK (rules 57 cited + 26 dispositioned / 83; accelerators 41 + 15 / 58);
kit_lint OK; doc_links --strict OK; wiki_render --selftest 32 pages / 0 unlisted
- kit: DK-65 "types are a banking lever and a width lever, not a byte lever" (kernel, when, cost, calibration fence, provenance;
the kernels file now states its own total "In all: DK-1 … DK-65" and SETUP Step 6 compares grep -c against it instead of a typed
64); intake row 6's milestone gains the canonical type layer (one definition per shape, widths proven by the bytes at bank time,
a bank refused for a duplicate definition or a raw address cast) + the type tools moved forward + G62/DK-65 in its columns; row 10
reads "short if Part C and Phase 6's type layer held"; G62 extended with the bank-time clause (G1–G67 kept); tool_dictionary:
lift_types + canon_sig_reconcile P10 → P6 and the five type tools' need-keys name the type layer at Phase 6 (the phase column is
one token — the corpus dir derives from it); the cookbook front page's type-verdict sentence (a NAME never moves a byte, a WIDTH
or SIGNEDNESS is the one place a type does, the permuter cannot reach it); the methodology's "Types — the two-sided verdict"
paragraph; the kit README's table + tree now name the two dictionaries and layout-contract.md; make kit-corpus regenerated the
tool index, the MANIFEST and the corpora (302 copies + 28 pointers)
- wiki: docs/wiki/Start-a-new-decomp-project.md — the three steps, what it installs / does not (the two dictionaries), the ladder
(11 rows), the five AI-use rules, the six inversions (raw casts → declared symbols; DK-65), the compiler question, the accelerators
one line each (58 rows), the four dry-runs, how it is kept honest; sidebar + Home rows; Tools-from-this-project rows for the kit
and the tool index; README bullets for both; SETUP row for decomp-architect/ (R21); Where-the-project-goes-next links the page and
records the probe PASS (2026-09-07); phase34-seed: task 0 PASSED, the kit carried whole through the flip and split later
- verify: wiki_render --selftest 12/12 + reachability 32 pages / 0 unlisted; doc_links --strict 58 documents / 451 links / 0 pending /
0 broken / coverage 65 of 65 (one BROKEN on the first draft — a foreign project's docs/ path cited in backticks — reworded);
kit_lint OK (leak 0 / placeholders 22 == 22 / syntax 0 / gitignore 75 identical); tool_census --check OK; 65 DK ids cited, 0
dangling; audit_public OK on the touched files; no build input changed
- log + checkpoint (NEXT = task 15, Max, Tier 1 — prompt Drew and wait for gate 2)