sots-re/findings/control-flow/seed-exposure-forward-test.md
alex be1426630c BQ: probe 1 predictions, committed before either run
Lane BQ (VM145) takes the seed-exposure predicate's first forward test.
Part 1b: ar-oracle-A-pre.sav + one End Turn from a LOAD must reproduce
7a8b3d5e... (it has only ever been reached by continuation). Part 1:
ar-oracle-A-post.sav in two fresh hooks=off processes must DIFFER, confined
to Player[32]'s research leaves, because that save carries ResTNm == '' for
the one player that can research.

Also records the exposure facts (ResTNm / NumDes / NumOwn / completions) for
every player on both inputs, and names a false-positive class in the predicate
before the run: four NPC players carry ResTNm == '' on the very turn whose
control agreed, and all four have NumOwn == 0.
2026-09-09 01:04:12 -04:00

13 KiB
Raw Blame History

The seed-exposure predicate's first forward test — probe 1 (parts 1b and 1)

  • Type: control-flow / determinism (two hooks=off measurements from saves already on disk; no build, no shim config change, no instrument)
  • Owner / date: lane BQ · 2026-09-09 · guest VM145 (sots-re-win10-145, 192.168.10.145)
  • Spec: findings/resolutions/2026-09-09-seed-exposure-is-a-predicate.md §6, probe 1
  • Tests: guides/method-rules.md rule 26 corollary (c) — the predicate written from lane AR's falsified P7, so far supported only by three states read after the fact
  • Depends on: findings/control-flow/raid-target-pick-verdict.md §6 (lane AR's pair)

1. Predictions, committed before either run (rule 2)

Everything in §1 and §2 was written and committed before the game was launched on VM145 and before any hash was read. It is not edited after the fact, only annotated with verdicts in §5.

1.1 What is actually at stake

The resolver ruled that the per-process AI client seed (row 326) is present in every process on every turn, and reaches the save only through a decision whose outcome set is larger than one given the state — and that whether such a decision is reached is a predicate on the pre-turn save. That ruling currently rests on three states read after their controls were run (lane AD's turn 28, lane AS's turn 16, lane AR's turns 38–39). It has never made a forward prediction.

This lane makes two, on states nobody has run, and both can fail.

1.2 Part 1b — the precondition

Procedure. ar-oracle-A-pre.sav (Frame 38, sha256 15b99255e1f03dab3e35ab8c1ac64f221cb5aa9321f113c7a6e3d1263c3f34ca), one fresh process, hooks=off, one End Turn, no other input.

P1b — committed. The resulting (Autosave).sav (Frame 39) hashes to 7a8b3d5eb3a60ebac9f40646d3e4b15768a24a0af047a439ce090c7cf38e8b38.

Why it matters. Lane AR's 15b99255… → 7a8b3d5e… step has only ever been reached by continuation — the second of two End Turns inside one process that started from ar-turn37-816raiders.sav. A calibration pair for the standalone must be a load → turn procedure. If P1b holds, the single-turn pair is certified in that form and is the first pair anywhere that exercises the trade-raid roll (four raid rolls, one word each, no encounter). If it fails, the pair remains valid only as the two-turn procedure from turn 37, and the resolution names the first suspect: the resave canonicalisation (determinism-oracle.md, round-trip section).

P1b-aux — committed, and it costs nothing. The same run also writes (Autosave EndTurn).sav, which is the state as End Turn is pressed — i.e. a resave of the file that was loaded. I predict it hashes to 15b99255…, the input's own hash. This is a direct test of the resave-canonicalisation suspect, taken in the same run whichever way P1b goes:

  • P1b holds and P1b-aux holds ⇒ load→resave is byte-exact here and the pair is clean.
  • P1b fails and P1b-aux fails ⇒ the divergence is present before the turn runs; it is the round trip, not the turn, and the resave canonicalisation is confirmed as the cause.
  • P1b fails and P1b-aux holds ⇒ the round trip is exact and the turn diverged from its continuation form. That is the interesting failure and it is not one the resolution anticipated; it would mean a load boundary changes turn 39's outcome, and it is a resolver case, not a lane result.
  • P1b holds and P1b-aux fails ⇒ the resave is not byte-exact but is behaviourally equivalent; the pair is certified and determinism-oracle.md's round-trip section needs a note.

1.3 Part 1 — the exposure test

Procedure. ar-oracle-A-post.sav (Frame 39, sha256 7a8b3d5e…), two fresh processes, hooks=off, one End Turn each, any encounter query resolved with Auto Resolve Peacefully in both.

P1 — committed. The two (Autosave).sav files differ, and the difference is confined to Player[32]'s TechTree/*, ResTNm, otch, Events, turnstats/…/tch and Summary/Checksum, while /Sim/RNG, /Sim/trdmgr, every Player[16] leaf and every player-0 fleet are identical.

The reasoning, and it is the predicate speaking: ar-oracle-A-post.sav carries ResTNm == '' for Player[32] (§2). By the AS precedent (as-turn15 → 16, 22 leaves, entered with ResTNm == '') and the row-326 precedent on turn1-state, that is a research-pick turn. So the predicate says, in advance, that lane AR's pair must not be extended by a turn — and this run is what makes that a measurement rather than an inference.

How P1 can be wrong, and the symptom of each way (rule 2):

way it could be wrong symptom
a producer supplied the target, so the pick had an outcome set of size 1 (as for player 32 on turn1-state) the two files agree byte-for-byte; the predicate survives but needs a producer gate, and lane L4's airesearch=on dump names which producer returned non-null
something else on turn 40 is exposed as well as the pick the files differ, but outside the named leaf set — e.g. in fleets, trdmgr, or Player[16]
the pick is exposed but its outcome-set is 1 for a different reason (only one affordable node) files agree; same follow-up as the producer case, and otch/TechTree at turn 40 says which node was taken
VM145 is not byte-faithful to the lineage P1b fails as well, and part 1b is the guard against reading part 1 off a guest that cannot reproduce anything

A negative here is a result, not a null. If the two files agree, the honest statement is "no exposed decision was reached on turn 40 either, and the pick is therefore producer-supplied on this state" — never "the AI is deterministic here" (rule 26 (c)).

1.4 A false-positive class in the predicate, named before the run

Read off the two saves (§2), and stated here because it is a pre-run correction to the predicate as the resolution words it:

ResTNm == '' at turn start is true of four players on ar-oracle-A-pre.sav — the turn whose control agreed byte-for-byte. Players 528 (Alien Menace), 544 (Peacekeeper Enforcer), 560 (Von Neumann) and 576 (Independent Colony) all carry ResTNm == '' on turn 38 and turn 39, and player 16 (the human) does too. They have NumOwn == 0: no colonies, no research income, no pick to make. So the raw predicate has a known false-positive class already sitting inside the very state that falsified AR's P7.

The sharp form the next lane should use is therefore:

ResTNm == '' at turn start, for a non-eliminated AI player with NumOwn > 0, names a research-pick turn.

On ar-oracle-A-post.sav exactly one player satisfies that: Player[32], NumOwn 18. That is the whole basis of P1, and it is why P1 names Player[32]'s leaves and no one else's.

(Note for honesty: players 496 and 512 — the two Spengler NPCs — hold non-empty ResTNm and also have NumOwn == 0. They are not evidence either way; they are listed in §2 for completeness.)

1.5 What this lane will not settle (rule 15)

  • Two processes, not three, for part 1 — rule 26's bar, matching AR's.
  • One state. Neither part says anything about ad-turn27, which is probe 2's job on VM146.
  • The producer gate is not run here unless part 1 comes out as agreement and time allows; if it does not, this document names it as the next step rather than guessing at it.
  • 0x0069dbb0's 3–40-turn fuse cannot fire in a one-turn-from-load run, by construction — so neither part can say anything about it, in either direction.
  • No instrument. hooks=off throughout, so this lane measures behaviour and never attributes it to a draw site. The consumer identification is probe 3's job.

2. The exposure facts, read off the saves before the runs (rule 26 (c))

uv run python3 verify/save-reader/save_reader.py --json, three saves on the AD/AR lineage. NumDes = the designs list length, NumOwn = the owners list length (both are the on-wire count prefixes; verified against the --dump tree at NumOwn/NumDes). "ships +" is the per-owner ShipID set delta from the previous save in the lineage.

2.1 ar-oracle-A-pre.sav — Frame 38, ModCount 2108, the input to part 1b

PID PlyrIdx name species NPC ResTNm NumDes NumOwn ships fleets
16 0 re (human) 0 no '' 6 3 5 5
32 1 The Eternal Empire 2 no BIO_EnvTail 47 18 243 59
496 2 Spengler 0 yes DRV_PlsFiss 0 0 0 0
512 3 Spengler 2 yes XNC_TrnsMorr2 0 0 0 0
528 4 Alien Menace 4 yes '' 19 0 0 0
544 5 Peacekeeper Enforcer 4 yes '' 1 0 0 0
560 6 Von Neumann 4 yes '' 6 0 0 0
576 7 Independent Colony 4 yes '' 1 0 0 0

Predicate reading for turn 38→39: the only player that can research holds a target (BIO_EnvTail), NumDes is constant at 47, NumOwn constant at 18. No exposed decision predicted — which is exactly what AR measured (three processes agreed). Part 1b is therefore a re-run of an agreeing turn from a load, and its only open question is the load boundary itself.

2.2 ar-oracle-A-post.sav — Frame 39, ModCount 2147, the input to part 1

PID PlyrIdx name species NPC ResTNm NumDes NumOwn ships fleets
16 0 re (human) 0 no '' 6 3 5 5
32 1 The Eternal Empire 2 no '' ← pick signature 47 18 245 59
496 2 Spengler 0 yes DRV_PlsFiss 0 0 0 0
512 3 Spengler 2 yes XNC_TrnsMorr2 0 0 0 0
528 4 Alien Menace 4 yes '' 19 0 0 0
544 5 Peacekeeper Enforcer 4 yes '' 1 0 0 0
560 6 Von Neumann 4 yes '' 6 0 0 0
576 7 Independent Colony 4 yes '' 1 0 0 0

Predicate reading for turn 39→40: EXPOSED. Player[32] enters with ResTNm == '' and NumOwn 18. otch moved 46 → 47 across turn 39 (BIO_EnvTail completed), which is the same shape AS recorded.

2.3 Ship completions on the lineage, for the fleet-assignment half of the predicate

transition ModCount PID 16 ships PID 32 ships reading
turn 37 → 38 2057 → 2108 −7408 (Zeta Fleet's destroyer, lost in the encounter) +8784, +8800 2 completions, into existing fleets — not a batch
turn 38 → 39 2108 → 2147 none +8816, +8832 2 completions, into existing fleets — not a batch

Two ships a turn into existing Freighters fleets is the quiet fleet consumer, not the thirteen-into-five-new-fleets batch that AD's turn 28 carried. designIds is constant at 95 and fleetIds at 64 across both transitions, corroborating "no design turn, no fleet creation".

So: on the input to part 1b the predicate says NOT exposed; on the input to part 1 it says EXPOSED, via the research pick, for exactly one player.


3. Procedure and configuration

hooks=off throughout, no build (rule 24 is satisfied trivially — nothing is compiled).

item value
guest VM145 sots-re-win10-145, 192.168.10.145
shim build C:\SOTS\shimdist-l4\binkw32.dll, BUILD_ID l4r-20260908T2208Z
config C:\SOTS\shimdist-l4\shim.cfg.l4off, unmodified — hooks=off, installs nothing
why this build lane L4 proved on this guest, with this exact DLL and this exact config that VM145 reproduces the campaign's published autosave oracle byte-identically (ai-order-capture.md §3: bb4fd9ac89f41e3b / 978041acd168b56e). It is the only hooks=off pair on VM145 with a published byte-fidelity result behind it
SavedGames reset to exactly one file — the run's input save — before every launch, so the Load dialog has one row and its position is re-derived from a screenshot anyway
main menu verified from a qm monitor screendump (tools/vmshot.py --one 145), never by sleeping
encounter query detected by sampling the Done pixel at (233, 673): ≈(183,18,0) query up, ≈(8,8,8) map. Auto Resolve Peacefully (667,641), Done (233,673)

VM145 as found, recorded so it can be put back (§8):

binkw32.dll  15,527,327 B  sha256 903527f4a698eea9fbe25f3a6236657c7d8348f994eef394696f187e5e554b97
             (= shimdist-recap, BUILD_ID recap-7584bad-20260908T0615Z)
shim.cfg     sha256 0ae410cc72fe155837d711c78543e14b1f5743310cd023298eb1e5bbd5457e71  (hooks=trace, lane R recapture)
SavedGames   9 files, saved to C:\SOTS\ui\preBQ\
game         not running

4. Results

(added after the runs; nothing above this line is edited)


5. Verdicts on the committed predictions

(added after the runs)


Proposed board rows

(added after the runs)