8.8 KiB
Is the residual fleet visit order an RNG draw or heap order? — the per-client draw ledger on ad-turn27
- Owner / date: lane BR · 2026-09-09 · guest VM146 (
sots-re-win10-146,re@192.168.10.146) - Held: VM146, from the time this prediction was committed. VM140 (reference, exclusive), VM141 (lane AZ) and VM144 (lane BS) untouched. VM145 free and untouched.
- Trigger:
findings/resolutions/2026-09-09-fleet-id-order-residue.md§4 / §8 — the single probe the resolver chose over two alternatives, because it is simultaneously run C (a third pinned sample, sizing the residual outcome set) and probe 3 (the per-client draw ledger). - Build:
bp-989c692-20260909T0505Z, lane BP's dist, still deployed atC:\SOTS\shimdist-bp(binkw32.dllsha2569de1c57a38e66800a9487f46f7e7abc4fea6efc05cd72319d911733e9d971f47). No build for this lane — the resolution costed it at "one fresh process, no build". - Input:
C:\SOTS\SavedGames\ad-turn27-two-raiders.sav, sha2561c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436, 100,809 B — re-verified on this guest before the run, equal to lane AD's and lane BP's published value. - Route: load (
ad-turn27-two-raiders.sav→ one End Turn), the same route as lane BP's three runs. This lane holds the route fixed, so it is unconfounded by lane BQ's per-history input (resolution §9.1).
0. The question, in one paragraph
Lane BP pinned all three AI client seeds on the campaign's richest AI turn and two fresh processes
still disagreed — but only in 35 leaves of 61,147, and all 35 are a single transposition: two
newly formed fleets exchange contents. The resolver decoded the ids and changed the frame: the ids
are not the variable (1970/1986/2002 are Player[32]'s own client, counters 123/124/125, minted in
that order in every process), the visit order over the ship groups needing a new fleet is. Two
mechanisms remain, and only two. H2: a draw on the per-process global generator at
0x00af6e58, which the seed pin does not touch and which already has two unnamed AI-band consumers
in the record (0x0079ea90+0x73, 0x005b9f00+0xc0). H1/H1b: an address-keyed container (or an
unstable comparator) walked in heap order — for which BP's own aielem node addresses supply a
measured precondition (same-size allocations landing in different relative orders in two processes
with identical decisions), the image base being constant on both guests (lane BQ). This probe
separates them by measurement: airng=on brackets each AI client's whole turn at
StrategyClient::OnResumePlaying and attributes every draw on every generator inside it to a
return address and a generator address. Lane I's inlined-draw inventory places no inlined draw
site between 0x680000 and 0x6e0000, so the observer is complete in the AI band.
1. Predictions, committed before the run
These are the resolution's §4 P1–P4, restated verbatim in substance, with the falsifier of each named. They are committed in their own commit, with no result in the file.
P1 (run C — the outcome set).
(Autosave).sav∈ {e913ff41188211c02d536da616337544e64133996cd7cc7a6521a8df1960226f,724528ffde9a7514b69ab9e82ed3b8c8ade63d622c0720de30503a73a92df11e} — lane BP's A/L file or its B file. A third file does not immediately mean either thing: it is ambiguous between the order outcome set exceeding 2 (k ≥ 3) and theairngdetour perturbing the run. The resolution names the disambiguation and this lane will run it if the guest allows: one more run ofshim.cfg.bppin(airng=off, plain run C). Under thek ≥ 3reading that plain run cannot land on a third distinct file with probability better than 1/3; under the perturbation reading it lands on one of BP's two.P2 (the headline — probe 3). In Player[32]'s
OnResumePlayingbracket:foreign_words=0,foreign_calls=0,residual=0, and noairngcensusrow whoserngis anything but Player[32]'s own client generator atclient+0x134— in particular none on0x00af6e58and none onSeedrecord #2's object. The same for clients 496 and 512.P3 (the ledger's shape — not load-bearing, recorded so it can be disagreed with). Player[32]'s own generator spends single-digit words inside its bracket, at return addresses in the AI band (
0x0068xxxx–0x006exxxxRVA-wise, i.e.vain0x0068_0000–0x006e_0000atexe base = 0x005e0000); clients 496 and 512 spend fewer than Player[32].P4 (the block). The
aiordersdump differs from lane BP's runs A and B only inside the proven noise set (the L/A mask: list 1 → words 1, 5, 8, 11; list 3 → 4–11; list 5 → 8–11; list 7 → 2–11; list 8 → 1–11; list 10 → 2–11; list 12 → 5–11; list 14 → 2–11; list 23 → 2–11) — plus, at most, the three-word transposition (list 8 idx=1 word0,list 10 idx=0 word0,list 10 idx=1 word0). Structure identical: 9 blocks, 81 elements, the same(pid, list, idx)sequence, the same per-list counts, player 32 emitting{1:3, 3:19, 5:15, 7:2, 8:3, 10:4, 12:12, 14:8, 23:15}.
1.1 How each prediction could be wrong, and the symptom
| way | symptom | what it would mean |
|---|---|---|
| H2 is right — some AI-band site draws on the global generator or on another object | ≥ 1 airngcensus row with rng ≠ client+0x134 inside a bracket |
P2 falsified, and that is a success. The row's ret_rva/va names the consumer. Follow-up is a global pin (RNG_Seed(0xaf6e58, K) after Application::Initialize), two fresh processes, predict byte-identical. Stop and post the address. |
| H1/H1b is right | foreign_words=0 everywhere; the census carries only the client's own generator |
P2 holds. RNG is excluded by measurement for the AI turn, and stage 2 becomes one bounded static read to place a hook on the group walk. Stop. Do not read the binary. Do not start stage 2. |
| an inlined draw on the AI path that the seven entry-point detours cannot see | residual > 0 on a bracket (left_delta > observed) |
P2 falsified in its residual=0 clause. The residual is a per-generator number measured off the object at +0x9c8, so it reports the invisible draw's existence without its address; the follow-up would be an image-wide immediate scan restricted to the AI band, which lane I already ran and which found nothing there — so this outcome would also contradict lane I. |
the airng detour perturbs the turn (rule 19) |
a third autosave file | Not separable from k ≥ 3 by this run alone — see P1. This is the caution the resolver put on the record and it will be reported as ambiguity, not resolved by preference. The disambiguation is one plain shim.cfg.bppin run. |
| the pin is half-applied | any aiseed call=… pinned=0, or a PIN MODE WITH NO PINS line, or a used=deadbeef wildcard hit |
The run is void and nothing is read from it. Checked in shim.log before any output file is opened. |
| a stale or wrong binary (rule 24) | BUILD_ID ≠ bp-989c692-20260909T0505Z in shim.log |
Void. No build is done by this lane, so the only failure mode is deploying the wrong dist. |
| the config carries an inherited defect | a live line inside what was meant to be a comment; an unnamed registered hook silently installed | Defended by the check that caught it in BP's own first draft: the non-comment diff of shim.cfg.bppin against shim.cfg.brprobe, quoted in §2.1, must be exactly three lines. |
| the click path lands somewhere else | wrong screen in a screenshot | Every step screenshotted and verified; never sleep-and-click. And the wall's /shot/<id>.png is a cached frame up to ~5 s stale (BP's gotcha, four wasted clicks) — wait 12–16 s or take two shots and use the second. |
1.2 What this probe cannot decide, whatever it says
It is one save, one procedure, one build, one route (load), and — for the ledger half — the
turn's own AI band. A foreign_words=0 result excludes a draw inside the bracket; it says
nothing about a draw taken before OnResumePlaying is entered whose value is carried into the
visit order (nothing in the record proposes such a path, and the seed pin is applied earlier still,
at RunAI, so a pre-bracket draw would have to be on a generator the pin does not touch and be
consumed later — named here so nobody reads P2 holding as more than it is). It also cannot identify
the container: that is stage 2's hook, and the resolver was explicit that the read must not begin
before this probe returns. The 3–40-turn fuse at 0x0069dbb0 cannot fire inside one turn of a load
and is untested here, exactly as in lane BP.
2. The procedure
(filled in with the run)
3. The result
(filled in with the run)
4. Verdict
(filled in with the run)