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).
- tools/argcheck.py: every call site whose in-scope declaration is narrower than the callee's real definition. 15,626
definitions read; 110,478 narrower declarations over 1,912 callees (86,701 K&R-empty, 23,777 positively narrow);
471 of them sit in a body that still holds a NEEDED $4-$7 pin — 323 bodies, the targeted draw, written to
.run/P36/engine/argcheck_draw.tsv.
Checked against the six agent cracks it was built from: it finds a7, a12 and a25, and it CANNOT find a13, whose
function is declared (void) in 131 of 138 sites AND defined (void) — a declaration comparison is blind to a definition
that is uniformly wrong. The census is a lower bound and the residual stays the oracle; the docstring says so.
Corrected before use: the scope column says which FIX is available, not whether the body can be banked — the cast route
is body-only at either scope (a7 closed a file-scope case that way).
- Drew challenged a10's 'needed by construction' verdict: nobody wrote the pin, so a plain-C spelling must exist. He is
right and the verdict is downgraded to its real scope — no spelling reaches the bytes in that TU's CURRENT declaration
environment. That environment is demonstrably wrong there: the file declares extern s32 func_801789AC(s32 arg0) while
the body calls it through a cast that drops the argument, the same class six agents cracked today. Restoring it was
tested at once and scores 3, not 0, so it is not the whole answer — but a verdict taken inside a distorted environment
is not a property of the function. func_80178970 moves to the structs/types phase list rather than being marked
permanent, with its reading attached.
- R14's documented premise corrected on bytes (agent a15): MIPS defines only PROMOTE_PROTOTYPES, not PROMOTE_MODE
(config/mips/mips.h:1153), so a narrowed parameter stays HImode and the extension still happens at the use. R14's
banked closes stand on their bytes, not on that rationale.