15 KiB
The per-history residue — the same save, two routes to turn 39, both reproducible
- Type: control-flow / determinism (two instrumented runs; one build, no static reading)
- Owner / date: lane BS · 2026-09-09 · guest VM144 (
sots-re-win10-144, 192.168.10.144) - Spec:
findings/resolutions/2026-09-09-fleet-id-order-residue.md§8 (VM144 paragraph) and §9 - Tests: §9.2's ranked candidates for the per-history input; §9.3's committed predictions (a)–(d)
- Depends on:
findings/control-flow/seed-exposure-forward-test.md(lane BQ — the residue, the click path, theDone-pixel test);findings/control-flow/pinned-seed-rich-turn.md(lane BP — the per-process residue, which this is not) - Rules exercised: 2 (predict first), 15, 19, 20, 21, 24, 25, 26 and its corollary (c), 28
1. Predictions, committed before the build was deployed and before the game was launched (rule 2)
Everything in §1–§3 was written and committed before binkw32.dll was copied onto VM144 and before
any hash was read. It is not edited afterwards, only annotated with verdicts in §5.
1.1 What is at stake
Lane BQ measured something the campaign had no model for: ar-oracle-A-pre.sav runs turn 39 one
way when the state is reached by continuation and another way when it is reached by a load, and both
routes are reproducible.
| route | processes | (Autosave EndTurn) |
(Autosave) |
|---|---|---|---|
continuation — load ar-turn37-816raiders.sav, End Turn, Auto Resolve Peacefully, End Turn |
3 (lane AR) | — | 15b99255… (F38) then 7a8b3d5e… (F39) |
load — load ar-oracle-A-pre.sav, End Turn |
2 (lane BQ) | 33e30092… |
4c356f59… |
23 leaves apart, 17 of them one AI fleet: Flt[1570 "Zeta Fleet V"] (PID 32). Both routes'
turn-39 input has it parked at Alpha Centauri (LocID 432, HFPlan False, FtFlg 12, both ships at
Range 9.0) — and so does turn 37's save, so it had already sat still for a turn. The continuation
issued it a move order on turn 39; both loads issued nothing.
So the pre-turn save does not fully determine the next turn's AI fleet-task decisions. §9.2 ranks the candidates and this lane's job is to say which survives:
- AI agent state the save does not carry —
AISystem::Writeemits nothing; the threeAIAgentsave blocks are cache. A task created on turn 38 exists on turn 39 only in the process that ran turn 38. Same class as the0x0069dbb0fuse and the client id counter. Leading. - Client generator stream position — rejected by the resolver: both routes are seed-insensitive on this turn (AR's three continuation processes had three seed sets and agreed; BQ's two loads had two and agreed).
- Server-side state not in the save — nothing in the record points here. Last.
1.2 P0 — the neutrality gate, and it is checkable at k = 1 here
Rule 19 asks for the measurement with the instrument removed. Unusually, both routes already have
hooks=off controls that agree with themselves, so rule 26 is satisfied on both sides and an
instrumented run agreeing with one is not a 1/k coincidence — k is 1 on each route.
P0 — committed. With
shim.cfg.bsruninstalled:
- continuation: the
(Autosave).savafter End Turn #1 is15b99255e1f03dab…and the(Autosave).savafter End Turn #2 is7a8b3d5eb3a60eba…;- load: the
(Autosave EndTurn).savis33e3009254f5acd1…and the(Autosave).savis4c356f5916f0e6e4….If either route misses either hash, that route is VOID. The instrument is not neutral on it and nothing — not one probe count, not one
airngrow — may be read from it. This is stated as a stop condition, not as a caveat.
1.3 The measurements — §9.3's (a)–(d), committed as mine, plus one of my own
P1 (= §9.3 a) — the block. In the continuation's turn-39
aiordersbatch, the block forpid=32carries a list-8 element whose first word is 1570 and at least one list-14 element whose first word is 1570. In the load's turn-39 block forpid=32, neither is present.Basis: in lane BP's dump the first word of a list-8, list-10 and list-14 element is the fleet id (list 8 idx0
ints=[ 2002 … ], list 14 idx0ints=[ 1970 0 … ]), and the save-side difference BQ measured is exactly aFPlanwith one waypoint (Wpt 320) appearing only in the continuation.
P2 (= §9.3 b) — the task. The two routes'
aiprobecounts for the turn-39 window differ in at least one row, and the difference is on a taskExecuteentry (probe idx 2–9) — either a task that fires in the continuation and not in the load, or the same task firing with a differentAcquireFleetsForTask(13) /IsClaimedByAnotherTask(14) count. Probe 11 (AssignFleetsAndIssueOrders) is entered in both routes, and probe 0 (RunTaskList) is non-zero in both — without which every other row is meaningless (rule 20 is built into the report).
P3 (= §9.3 c) — the draws. In every
OnResumePlayingbracket on both routes:foreign_words=0,foreign_calls=0,residual=0, and noairngcensusrow whoserngis anything but that client's+0x134. The two routes' per-client word counts differ by at most the cost of the task P2 names. RNG is not the mechanism, and this is the measurement that says so rather than the inference.
P4 (= §9.3 d) — the pre-turn states. The continuation's own frame-38 autosave and the load run's
(Autosave EndTurn).savdiffer in exactly one leaf,/CD[1]/NPrvVa(+5.00), under--floats bits --mask resave. Restated: the two routes enter turn 39 from the same state, so whatever differs is not in the file. (BQ measured this without an instrument; if it moves under mine, the instrument moved it and P0 will have said so first.)
P5 — mine, the exposure fact the standing instruction asks for.
airngemits one bracket row perStrategyClient::OnResumePlayingentry carryingagent=, so it reports which clients actually run an AI turn. I predict three clients run on both routes —pid32, 496 and 512 — and that players 528/544/560/576 produce no bracket row with a non-null agent, matching lane BP's count of three clients from seven non-human players on the same lineage.NumOwn == 0gates nothing: 496 and 512 haveNumOwn == 0and are predicted to run.
How each can be wrong, and the symptom (rule 2):
| way it could be wrong | symptom | what it would mean |
|---|---|---|
| the residue is not in the AI's emission at all | P1 fails in the null direction: both routes' pid-32 blocks are element-for-element identical | the divergence is downstream of BuildTurnCommands — in the server's application of the block, or in ProcessFleetMovement. This relocates the question and is the more valuable outcome, because it would exonerate the whole AI-agent-state candidate in one run |
| the block differs but no probe does | P1 holds, P2 fails | the task set is the same and the gathering differs — the fleet set AcquireFleetsForTask returns. That is BR's stage-2 territory (AssignFleetsAndIssueOrders 0x006c16c0 and its 992-byte hub), and the two lanes converge on one function from two directions |
| a draw is involved after all | P3 fails: a non-zero foreign_words, or a census row on 0x00af6e58 |
the resolver's rejection of candidate 2 was wrong; the return address names the consumer and the follow-up is a global pin |
| the routes do not enter turn 39 from the same state | P4 fails on a leaf other than NPrvVa |
there is a save-visible difference and the whole "not in the file" framing is wrong. This is the one failure that would overturn BQ's headline rather than extend it |
| the instrument perturbs | P0 fails | the run is void; report the miss and stop |
| more or fewer than three clients run | P5 fails | the client count is a property of the state, not of the lineage, and rule 26 (c)'s "read the predicate against who actually runs" needs a per-save count |
A null result is a real result. If both routes produce identical AI fleet-task probe sequences and identical blocks, I will report that as the finding, not hunt for a difference elsewhere.
1.4 What this lane will not settle (rule 15)
- One process per route. Each route's reproducibility is already established by two or three
hooks=offprocesses (AR, BQ); this lane adds the instrument, not a third control. So it can say what the AI emitted on each route; it cannot add evidence about whether a route is reproducible. - No static reading, no build of
game/ai. If the answer is "the fleet set differs", naming the container is BR's stage 2, not this lane's. - The
0x0069dbb0fuse cannot fire in a load→one-turn run by construction, so the load arm says nothing about it. The continuation arm runs two turns from a load, which is still inside the 3–40-turn fuse window, so neither arm bears on it in either direction. - The research probes (16–19) are not installed. BQ measured
candidatesTried=1and an agreeing pick on this lineage; four fewer detours is four fewer ways to fail P0. So this lane says nothing about the research half. - Turn 38's encounter is auto-resolved peacefully on the continuation arm, and that is only safe
here because the other side has nothing to fight with (lane BQ:
Auto Resolve Peacefullymeans "I commit no ships", not "no combat occurs"; on a later turn a planet fired and killed a different number of raiders in each process). AR's turn-38 encounter reproduced across three processes, which is the only reason this procedure is admissible at all. It does not generalise. aiorders.deep=off, so list 8's route vector and list 10's counted vector are behind pointers and are absent from the dump. The fleet id is in the element window; the waypoint list is not.
2. Exposure facts, read off the inputs before the runs (rule 26 (c), with the route)
Read with verify/state-checksum/state_checksum.py's leaf walk over the typed tree. The standing
instruction: record which players have an AI client, and record the route as part of the
procedure. The client list is a run-time fact, so it is predicted in P5 and reported in §4; what the
saves carry is below.
2.1 ar-turn37-816raiders.sav — Frame 37, the continuation arm's input
| PID | name | NPC | ResTNm |
NumOwn |
|---|---|---|---|---|
| 16 | re (human) |
no | '' |
3 |
| 32 | The Eternal Empire | no | BIO_EnvTail |
18 |
| 496 | Spengler | yes | DRV_PlsFiss |
0 |
| 512 | Spengler | yes | XNC_TrnsMorr2 |
0 |
| 528 / 544 / 560 / 576 | Alien Menace / Peacekeeper Enforcer / Von Neumann / Independent Colony | yes | '' |
0 |
Flt[1570 "Zeta Fleet V"] (PID 32) on turn 37: LocID 432, HFPlan False, FtFlg 12,
NShips 2, both ships Range 9.0. Identical to its turn-38 state — so the AI left it parked on
turn 38 in the continuation too, and the order it issued on turn 39 is not a continuation of an order
in flight.
2.2 ar-oracle-A-pre.sav — Frame 38, the load arm's input and the continuation arm's midpoint
Per-player table as lane BQ published it (§2.1 there): the only player that can research holds a
target, NumDes 47 constant, NumOwn 18 constant, two completions a turn into existing
Freighters fleets — no new fleet is formed on this turn, which is why BP's per-process visit
order has nothing to vary and why this turn shows no per-process residue.
Flt[1570 "Zeta Fleet V"]: LocID 432, HFPlan False, FtFlg 12, NShips 2, ships 5840 and 6144
both at Range 9.0. This is the leaf set the two routes disagree about.
Predicate reading, both routes: no research pick (target held), no design turn, no fleet-assignment batch, no AI fleet at an enemy colony. Rule 26 (c) screens this turn as not exposed — and it is exposed anyway, through a term the predicate does not have. That is the point of the lane.
3. Procedure and configuration
3.1 The two runs
| route | procedure | |
|---|---|---|
| run C | continuation | SavedGames reset to exactly ar-turn37-816raiders.sav; fresh process; Load → Single Player → row 1 → OK; End Turn; the turn-38 encounter resolved with Auto Resolve Peacefully then Done; End Turn |
| run L | load | SavedGames reset to exactly ar-oracle-A-pre.sav; fresh process; Load → Single Player → row 1 → OK; End Turn |
Both saves are copied in from verify/results/saves/, which moves the Load-dialog rows; with exactly
one file the dialog is one row and it is screenshotted and re-derived anyway (lane BQ's tip). The
Done pixel at (233,673) is sampled to detect the encounter query rather than assumed
(≈(183,18,0) query up, near-black on the map). One click per helper call with a screenshot between
(lane M, confirmed by BQ on a second guest); ≥ 9 s after schtasks /Run before believing a shot
(lane AP's nine-minute gotcha).
3.2 Configuration — shim.cfg.bsrun, one file, both runs
| item | value |
|---|---|
| guest | VM144, held by lane BS |
| build | C:\SOTS\shimdist-bs\binkw32.dll, built fresh in /srv/re-lab/build/sots-engine-bs (rm -rf'd first, rule 24) from worktree wip/bs (rule 21) |
| config | shim.cfg.bsrun — hooks=trace with all 27 registered hooks named off (the # exhaustive marker; tools/check_shim_configs.py passes) |
| instrument | aiorders=on aiorders.words=32 aiorders.deep=off; aiprobes=16 (probes 0–15: the control+pass recorder, every task Execute entry the table carries, the three emission exits, the hub, the claim test, BuildTurnCommands); airng=on airng.pin_seed=off |
| off | probes=off, watch=off, airesearch=off, aidesign=off, aiseed=off, no pin of any kind |
aiseed=off means the RunAI net-id list is not logged — the brief's config says every template
hook off by name, and aiseed=log would have been one more detour on RunAI than the brief asked
for, on a run whose whole value is a k = 1 neutrality check. The exposure fact is taken instead from
airng's per-bracket rows, which carry pid and agent for every OnResumePlaying entry — the
clients that actually run, measured at the bracket rather than at the seed. §4 reports it as such.
3.3 VM144 as found, recorded so it can be put back
binkw32.dll 22,972,439 B sha256 479b8614d2417603b64e66482e429ecd3cdfe4033a2c99969ca91553642e517d
(= shimdist-l3, BUILD_ID l3cont2-0117495-20260908T2124Z)
shim.cfg sha256 692dabb6f00343bfcc2f86d62ade827c295acc4630a18a1f2ddcebd53640978d
SavedGames 15 files (hashes in §8)
game RUNNING at the main menu (pid 8408), screenshot-verified