Appearance
aowlspt/callproof
Source: aowl/src/aowlspt/callproof.nim — 749 lines.
THE LIVE EXPERIMENT that settles the by-value aggregate convention.
WHY AN EXPERIMENT AT ALL, WHEN THE BYTES ALREADY SAY SO
abi/aowlspt_callrva.h records the callee's own instructions from four methods on this build. Those bytes are strong: they are what the CPU will execute, not an inference about it. But they establish what the CALLEE expects, and not that OUR CALLER produces it. The two are different claims and only one of them has been tested. CLAUDE.md 9b: an offline disassembly proof once established, correctly, which field SetGameModeText writes -- and could not establish that the field reaches the screen. It did not.
THE TRAP THIS IS BUILT AROUND
"The call returned without faulting" is NOT evidence. A wrong convention returns plausible garbage, and that is the single most expensive class of bug in this project. Physics::Raycast would be the worst possible subject: it returns a bool, and a bool from a completely wrong call is indistinguishable from a bool from a right one.
So the subject is a method whose answer is known EXACTLY, in advance, by arithmetic nobody has to trust:
UnityEngine.Vector3::Dot((1,2,3), (4,5,6)) = 4 + 10 + 18 = 32.0 UnityEngine.Vector3::Cross((1,2,3), (4,5,6)) = (-3, 6, -3)
Every one of those inputs and outputs is exactly representable in binary32, so the assertion is EQUALITY, not a tolerance. There is no arrangement of registers other than the right one that produces 32.0 and (-3,6,-3).
AND IT CAN FAIL. checkRival deliberately makes the SAME call under the rival convention -- the 12 bytes packed into the registers themselves rather than passed by pointer -- and requires that it does NOT return 32.0. If both conventions returned 32.0 the experiment would be a check that cannot fail, and this reports INCONCLUSIVE rather than claiming a pass. That is the whole design: describe the input that makes the check fail, or you have not written a check.
WHY IT IS SAFE TO RUN ON A LIVE CLIENT
Vector3::DotandVector3::Crossare PURE ARITHMETIC on two buffers this module owns. They touch no game state, allocate nothing, and have no side effect of any kind. There is nothing for a wrong answer to damage.- No
GameWorld, no camera, no raid, no UI, no live object. It runs at the main menu, at profile-select, anywhere. It never gates onwhenReady("EFT.GameWorld")-- fact #141, a check that cannot fail, which killed the FOV mod again at 8.375s while logging "the game world is up" from the character screen. - The rival-convention call dereferences a float bit pattern as an address. That is an access violation by design, and it runs inside the ONE guard in
aowlspt_callrva.h, which catches it and returnscoFaulted. A caught AV is the EXPECTED reading for that check, not a crash. - Default OFF, runs ONCE, and self-disables permanently after the first fault beyond the one the rival check expects.
HOW THE COORDINATING SESSION RUNS IT
Flag: callProof, default off. Set it with python tools/hostcfg.py set callProof on -- never by hand-editing aowlspt-host.json, because hostcfg.py checks the key against what is actually read and a typo otherwise produces a flag nobody consumes.
Then read the verdict with python tools/hostlog.py grep "call-proof". Every line is prefixed call-proof: and every check reports exactly one of PASS / FAIL / INCONCLUSIVE. The summary line is the answer:
call-proof: VERDICT by-value aggregates pass BY HIDDEN POINTER -- 5 PASS, 0 FAIL, 0 INCONCLUSIVE
Any FAIL, or any INCONCLUSIVE, means the convention is NOT settled and nothing downstream should be built on it. There is no fourth outcome and no silent one.
Types
ProofOutcome
nim
ProofOutcome* = enum
pvPass
pvFail
pvInconclusiveaowl/src/aowlspt/callproof.nim:171
ProofLine
nim
ProofLine* = object
name*: string
outcome*: ProofOutcome
detail*: stringaowl/src/aowlspt/callproof.nim:176
ProofReport
nim
ProofReport* = object
lines*: seq[ProofLine]
passes*: int32
fails*: int32
inconclusive*: int32
verdict*: string
wiring*: string
## The resolved address, the module base and the declared prologue
## length, printed every run so a zero can never be ambiguous again.aowl/src/aowlspt/callproof.nim:181
Routines
tag
nim
proc tag*(o: ProofOutcome): stringaowl/src/aowlspt/callproof.nim:197
callProofDisabled
nim
proc callProofDisabled*(): boolaowl/src/aowlspt/callproof.nim:659
runCallProof
nim
proc runCallProof*(includeRival: bool = true): ProofReportRun the whole experiment ONCE. A second call returns an empty report rather than repeating game calls -- nothing here is a per-frame path and nothing about it needs to be.
aowl/src/aowlspt/callproof.nim:661
formatCallProof
nim
proc formatCallProof*(r: ProofReport): seq[string]One line per check plus the verdict, ready to hand to a mod's logger. Every line carries its own outcome word so hostlog.py grep call-proof shows the whole result and not just the happy summary.
aowl/src/aowlspt/callproof.nim:736

