2e97ff1461
Re-entry discriminator came back a CONFIRMED BUG: an unlisted transfer-list item does not survive a fresh FUT session, so our representation cannot reconstruct trade-pile membership. Evidence acquisition per instruction, corpus and PE first, no guessing. Adds route_table_dump.py: static read-only dump of CardsDLL's route table from the on-disk PE, resolving VA->file offset through the real section table instead of assuming a single .text mapping. Output preserved as evidence. It settles "is /tradePile the only relevant route?" -- the table holds 45 routes plus 3 empty admin slots, and row 30 `ut/%s/tradePile` is the ONLY trade-pile route. There is no trade-pile items route. That plus three existing PE facts narrows the representation to exactly one candidate by ELIMINATION rather than choice: the route carries only twelve-atom auction records; `pile` (0x226) has no arm in the item deserializer so membership is conferred by the owning list and cannot be added as a field; of the twelve atoms only tradeState expresses lifecycle; and tradeState's closed vocabulary (active=1 inactive=2 expired=3 closed=4) has exactly one value not already spoken for. So an unlisted item can only be an auctionInfo record with tradeState "inactive". Tagged INFERRED-BY-ELIMINATION, not CONFIRMED: the remaining unknown is whether the Flash Transfer List RENDERS such a record in the unlisted section. Records the acceptance test (survive a full FUT reload) and the revised invariant that a transition is complete only when a fresh session reconstructs the same visible state. No behaviour change in this commit.