rules: 18 - measure first, the lab exists; static reading explains what you measured

This commit is contained in:
alex 2026-09-08 11:20:30 -04:00
parent 95b2bc81cf
commit 351acc07c3

View file

@ -186,3 +186,28 @@ coverage 89% -> 100%. Ghidra's size is also simply wrong sometimes — it gave 7
that is 7,641 and ends mid-instruction.
**Never trust a function's end. Disassemble to the next function start and find the real boundary.**
## 18. Measure first. The lab exists.
We have the game running under a hook framework, a debugger, 11 curated saves, a byte-identical
autosave oracle and a state-checksum tool that localises to named leaves. **Use them before deriving
anything.**
The RNG gap is the case study. Static analysis spent several lanes on it and produced a complete
draw-site inventory with an unexplained count — genuinely good work that could not close. The answer
came from ten minutes of live hooking: return-address capture on the entry points attributed every
word in one turn, and the dominant consumer turned out to hang off a **virtual** edge that no
direct-edge closure could ever have reached.
The general shape: **static reading is for explaining what you measured, not for predicting it.**
Derivation is the fallback when the path cannot be reached, not the default.
A question of the form *"what writes this?"*, *"how many times does this run?"*, *"does this branch
ever fire?"* is a **watchpoint or a hook**, not a week of reading. Open items that fit that shape
right now: the `Player.Status` writer between tail phase 31 and the autosave; the `TShn`/`ltis`
writer; `Summary.Checksum`'s inputs; whether a trade-raid roll ever succeeds (a word count cannot
separate "no success" from "empty candidate list" — a hook on the callee separates them instantly).
Corollary, from the same session: **search the notes before the binary.** The dominant RNG consumer
was already identified in `strategic-turn-internals.md` months of lanes earlier. What was missing was
never the identification — it was the connection.