BP has a per-PROCESS input (two pinned processes disagree); this lane has a per-HISTORY input (two load processes agree with each other and disagree with the continuation). One datum against the ASLR reading as stated: the exe base was identical in all five VM145 processes (0x00f40000, delta +11796480), so any image-base hypothesis has to name which allocation it means. Probe 3's ledger taken twice on ar-oracle-A-pre - once by continuation, once by load - now speaks to both.
621 lines
47 KiB
Markdown
621 lines
47 KiB
Markdown
# 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)*
|
||
|
||
### 4.0 What was run
|
||
|
||
Five fresh processes on VM145, all with `C:\SOTS\shimdist-l4\binkw32.dll` (`BUILD_ID
|
||
l4r-20260908T2208Z`) and `SavedGames` reset to exactly one file before each launch. The Load dialog
|
||
was screenshotted every time and the row re-derived: with one file it sits at **(400, 262)**, and it
|
||
sat there for all five runs. Main menu verified from a `qm monitor` screendump before every click
|
||
path; no run was driven by sleeping.
|
||
|
||
**Instrument armed and verified from `shim.log`, not assumed** (rule 1). For all four `hooks=off`
|
||
runs the log reads exactly `config: hooks=off` / `hook: disabled by config` — nothing installed, no
|
||
`ignoring unknown key` lines.
|
||
|
||
| run | input | config | End Turn | encounter | `(Autosave EndTurn).sav` | `(Autosave).sav` |
|
||
|---|---|---|---|---|---|---|
|
||
| **1b-A** | `ar-oracle-A-pre` (F38) | `l4off` | 1 | none | 107,477 `33e30092…` | 107,732 `4c356f59…` |
|
||
| **1b-B** | `ar-oracle-A-pre` (F38) | `l4off` | 1 | none | 107,477 **`33e30092…`** | 107,732 **`4c356f59…`** |
|
||
| **1-A** | `ar-oracle-A-post` (F39) | `l4off` | 1 | Venkman, **peaceful** | 107,661 `1a9d937b…` | 108,580 `56980aa0…` |
|
||
| **1-B** | `ar-oracle-A-post` (F39) | `l4off` | 1 | Venkman, **peaceful** | 107,661 **`1a9d937b…`** | 108,541 **`b36ac0ec…`** |
|
||
| **1-R** | `ar-oracle-A-post` (F39) | `l4research` | 1 | Venkman, **peaceful** | 107,661 **`1a9d937b…`** | 108,571 **`28bbd9b5…`** |
|
||
|
||
Run **1-R** is the producer-gate run the resolution names (§4.4); it is the only instrumented run and
|
||
it was taken *after* the two `hooks=off` processes, not instead of them.
|
||
|
||
### 4.1 Part 1b — P1b is **FALSIFIED**, and the load→turn procedure is nonetheless a valid pair
|
||
|
||
`ar-oracle-A-pre.sav` + load + one End Turn does **not** reproduce `7a8b3d5e…`. It produces
|
||
`4c356f5916f0e6e4…` — and it produces it **in two fresh processes, byte for byte**, at both snapshot
|
||
points.
|
||
|
||
> **The load→turn procedure agrees with itself and disagrees with the continuation.** That is not
|
||
> non-determinism; it is a different procedure with a different, reproducible answer.
|
||
|
||
`state_checksum --floats bits --mask none` against AR's `ar-oracle-A-post.sav`: **23 leaves**, and
|
||
they are not the research leaves at all.
|
||
|
||
| leaves | what |
|
||
|---|---|
|
||
| 1 | `/CD[1]/NPrvVa` 501.13 → 506.13 — the load-boundary counter (§4.3) |
|
||
| 2 | `/Summary/Checksum` (derived), `/Sim/ModCount` 2147 → 2145 |
|
||
| **17** | **`Flt[1570 "Zeta Fleet V"]` (PID 32)** — `FPlan` only-in-A, `HFPlan` True→False, `FtFlg` 13→12, `LocID` 0→432, `Pos`/`FtOrig`/`PrvPos` all three components, both ships' `Range` 7.0 → 9.0 |
|
||
| 2 | `Sys[432 "Alpha Centauri"]` `NumFlts` 0→1, `Flt` only-in-B, `FFlags` 0→2 |
|
||
| 1 | `Flt[914 "Nu Fleet III"]` `HLay` False→True, `Lay` only-in-B |
|
||
|
||
Read off `ar-oracle-A-pre.sav`: `Zeta Fleet V` enters turn 39 parked at Alpha Centauri (`LocID 432`,
|
||
`HFPlan False`, both ships at full `Range 9.0`).
|
||
|
||
- **In AR's continuation** the AI issued it a move order — a `FPlan` with one waypoint (`Wpt 320`,
|
||
`FPsp2 2.0`, `FPeta2 3`, `pnd 432`), the fleet left the system, `FtFlg` went to 13 and the ships
|
||
burned 2 ly of range.
|
||
- **In both of my loads** the AI issued nothing: the fleet is still at Alpha Centauri with full
|
||
range, and the system's `NumFlts` records it as present.
|
||
|
||
**This is an AI fleet-task decision — the exact consumer class the resolution lists as
|
||
unidentified — and it came out differently across the load boundary while coming out identically in
|
||
two processes on each side of it.** Two `hooks=off` processes from turn 37 agree (AR, plus AR's
|
||
instrumented third); two `hooks=off` processes from a load of turn 38 agree (this lane). They do not
|
||
agree with each other.
|
||
|
||
So the honest statement, and it is the one that matters for the standalone:
|
||
|
||
> **`ar-oracle-A-pre.sav → 7a8b3d5e…` is NOT a load→turn pair and must not enter
|
||
> `determinism-hashes.txt` as one.** What *is* certified, by two fresh processes, is a different
|
||
> pair: `ar-oracle-A-pre.sav` → **(load, one End Turn)** → `(Autosave EndTurn).sav`
|
||
> `33e3009254f5acd1…`, `(Autosave).sav` `4c356f5916f0e6e4…`.
|
||
|
||
The single-turn pair still exercises the trade-raid roll (four raiders parked, no encounter), so the
|
||
standalone gets its first trade-raid calibration pair — with the load→turn hashes, not AR's.
|
||
|
||
### 4.2 The resave canonicalisation is **not** the cause — and the round-trip rule needs one addition
|
||
|
||
The resolution named the resave canonicalisation as the first suspect if P1b failed. It is
|
||
exonerated, and the measurement that exonerates it is P1b-aux.
|
||
|
||
**Pre-turn form** (`ar-oracle-A-pre.sav` vs its own resave, my `(Autosave EndTurn).sav`): **1 leaf**.
|
||
Not `Status`, not `Checksum` — those are already 0/consistent in a pre-turn file, exactly as
|
||
`determinism-oracle.md` says. The one leaf is `/CD[1]/NPrvVa`, +5.00.
|
||
|
||
**Post-turn form** (`ar-oracle-A-post.sav` vs my run 1-A `(Autosave EndTurn).sav`): **6 leaves** —
|
||
`Summary/Checksum`, the four `Player.Status` 4 → 0, and `/CD[1]/NPrvVa` +5.00. Applying the
|
||
campaign's documented rule (`--mask resave`, "mask every `Player.Status` and `Summary.Checksum`;
|
||
**nothing else varies**") leaves **exactly one leaf standing**:
|
||
|
||
```
|
||
policy: floats=bits mask=resave [masked: Checksumx1, Statusx8]
|
||
DIVERGED: 1 leaf difference(s)
|
||
/CD[1]/NPrvVa: 501.13360595703125 -> 506.13360595703125
|
||
```
|
||
|
||
> **Correction to `determinism-oracle.md`, "Round-trip stability" / "Recommended canonicalization
|
||
> rule" (rule 11):** *"Nothing else varies"* is **false** on this save. `/CD[1]/NPrvVa` advances by
|
||
> exactly **+5.00** across a load, in both the pre-turn and the post-turn form, and `--mask resave`
|
||
> does not cover it. The rule was derived on `ref-turn2` / `turn2-state`, three-player early-game
|
||
> saves; this is a two-empire turn-38 save with a populated `CD[1]` diplomacy block, and the ratchet
|
||
> broke on new content exactly as rule 27 describes.
|
||
|
||
What `NPrvVa` is, measured rather than assumed: it sits in the `CD[1]` custom-data block next to
|
||
`NPrv` (a count) and `NPrvId` (a player id, 16 here), so it reads as a per-player provocation /
|
||
threat value. Its observed behaviour: **+5.00 per turn boundary crossed, plus +5.00 across the load**
|
||
(496.13 at F38 → 501.13 at F39 in AR's process; 496.13 loaded → 501.13 at the End Turn press →
|
||
506.13 at F39 in mine). It is **not** a monotone counter: on turn 40 it *fell*, to 461.48 in run 1-A
|
||
and 476.65 in run 1-B, tracking that turn's combat.
|
||
|
||
Because it advances on the load itself, **no load→turn run can ever reproduce a continuation's hash
|
||
on this leaf**, independently of anything the AI does. P1b was unsatisfiable on `NPrvVa` alone; the
|
||
other 22 leaves are the substantive result.
|
||
|
||
### 4.3 Part 1 — P1 is **half right, and wrong about the mechanism**
|
||
|
||
The two `hooks=off` processes **differ**: `56980aa086e1a145…` (108,580 B) vs `b36ac0ec2986f3a8…`
|
||
(108,541 B). `state_checksum`: **144 leaf differences**.
|
||
|
||
**But the `(Autosave EndTurn).sav` is identical in all three turn-39 loads** (`1a9d937b…`, 107,661 B,
|
||
runs 1-A, 1-B and 1-R). The load is perfectly reproducible; the divergence is entirely inside the
|
||
turn.
|
||
|
||
And the divergence is **not** the research pick. Where the 144 leaves live:
|
||
|
||
| leaves | subtree |
|
||
|---|---|
|
||
| 50 | `/Sim/crep[29]/*` — the combat report (per-ship damage, weapon rows, `cpk`, `cdt`) |
|
||
| 41 | `Flt[2274 "Sigma Fleet VII"]` (PID **32**) — the AI fleet in the fight: `NShips` 5 vs 6, three different ship ids, hull health, 16 `TH`/`THM` pairs on one ship |
|
||
| 8 | `Sys[224 "Venkman"]` — `Pop`, `PopC`, `Infra`, `Res`, `Suit`, `RepCur`, `RepMax`, `pbon` |
|
||
| 6 | `/CD[1]/CmbR[2]/…/TacReports` |
|
||
| 4 | `/Sim/turnstats/history/…` |
|
||
| 20 | `Player[16 "re"]`: `BnkPr`, `BnkEl`, `otch`×6, `owep`×4, `odes`×2, `ShipRecs`, `preps`, the turn-40 `EvMsg` |
|
||
| 13 | `Player[32]`: `Maint`, `ShipRecs`×8, `odes`, `owep`×2, `otch`×2, the turn-40 `EvMsg` |
|
||
| 2 | `/Sim/ShipIDs[]`, `/Summary/Checksum` |
|
||
| 1 | `/CD[1]/NPrvVa` |
|
||
|
||
The two `EvMsg` strings say what happened in one sentence each:
|
||
|
||
```
|
||
A: "...147,834,923 Imperial citizens were killed. ... 2 enemy ships were destroyed."
|
||
B: "... 78,818,284 Imperial citizens were killed. ... 1 enemy ship was destroyed."
|
||
```
|
||
|
||
**The AI's `Sigma Fleet VII` attacked player 16's colony Venkman, the human committed no ships
|
||
("No ships available", `Auto Resolve Peacefully` in both runs), and the planetary defences killed
|
||
two raiders in one process and one in the other.** Ship deltas confirm it exactly: both runs
|
||
completed the *same* two ships for PID 32 (`+8848, +8864`); run A lost `7744` and `7952`, run B lost
|
||
`8000`. Nothing else about the turn moved.
|
||
|
||
**Now the leaf-by-leaf verdict on what P1 named:**
|
||
|
||
| P1 clause | verdict |
|
||
|---|---|
|
||
| the two files **differ** | **CONFIRMED** |
|
||
| `/Sim/RNG` identical | **CONFIRMED** — the 2,503-byte raw block is byte-equal (`a689d7a3…`) in both |
|
||
| `/Sim/trdmgr` identical | **CONFIRMED** — no `trdmgr` leaf in the diff |
|
||
| **every player-0 fleet** identical | **CONFIRMED** — all five PID-16 fleets (3744, 6544, 33, 49, 81) match on id, `LocID`, `Pos` and ship count |
|
||
| difference confined to `Player[32]`'s `TechTree/*`, `ResTNm`, `otch`, `Events`, `turnstats`, `Checksum` | **FALSIFIED** — no `TechTree` leaf and no `ResTNm` leaf differs at all, and the difference reaches a colony's population, both players' banks and the combat reports |
|
||
| **every `Player[16]` leaf** identical | **FALSIFIED** — twenty `Player[16]` leaves moved |
|
||
|
||
**The research pick did not vary.** Both processes set Player[32]'s `ResTNm` to **`BIO_GrvAdpt`**,
|
||
`otch` 47 in both, `NumDes` 47, `NumOwn` 18. The predicate's own signature — `ResTNm == ''` at turn
|
||
start for the one player that can research — fired, a pick *was* made, and it was the **same pick in
|
||
both processes**.
|
||
|
||
### 4.4 The producer gate, run — and the answer is better than "a producer supplied it"
|
||
|
||
The resolution's follow-up for exactly this outcome: *"a producer supplied the target … and the
|
||
predicate needs a producer gate. One run with lane L4's `airesearch=on` dump names which producer
|
||
returned non-null."* That config is on the guest already (`shimdist-l4\shim.cfg.l4research`), so it
|
||
cost one run and no build. Run **1-R**, same input, same procedure, same peaceful resolution.
|
||
|
||
`verify/results/shim/bq/bq-res-aiorders.txt`, the whole research record for the turn:
|
||
|
||
```
|
||
---- airesearch sel=1 agent=0x32446560 ... curTarget=0x00000000 species=2 ----
|
||
aicand sel=1 idx=0 agent=0x32446560 slot=0x3244669c w0=0x00000002(2) w1=0x00000001(1)
|
||
airesult sel=1 candidatesTried=1 chose='BIO_GrvAdpt' (ptr=0x0463fd3c)
|
||
---- airesearch sel=2 ... curTarget=0x04707c50 species=0 ---- (PID 496, target held)
|
||
---- airesearch sel=3 ... curTarget=0x0d6c34a8 species=2 ---- (PID 512, target held)
|
||
|
||
aiprobe idx=16 AIResearch::ProducerA turn=3 total=3
|
||
aiprobe idx=17 AIResearch::ProducerB turn=3 total=3
|
||
aiprobe idx=18 AIResearch::FallbackIndex turn=0 total=0
|
||
aiprobe idx=19 AIResearch::FallbackArm turn=0 total=0
|
||
```
|
||
|
||
> **It was not a producer short-circuit. Player[32] reached producer C — the candidate walk — and the
|
||
> candidate list had length ONE.** Producers A and B were entered once per AI player and both
|
||
> returned null for the `curTarget == 0` agent; `SelectResearchTarget` ran; `TryResearchCandidate`
|
||
> was offered exactly one candidate and accepted it; the `0x006b36e0 & 7` fallback rotation was never
|
||
> reached (`FallbackIndex` / `FallbackArm` both 0).
|
||
|
||
`candidatesTried = 1` is the whole explanation. **The outcome set of that pick is a singleton because
|
||
the candidate vector holds one element**, and no draw on any stream can change a one-element choice.
|
||
|
||
That is a *different* mechanism from the one the resolution guessed, and it is strictly more useful,
|
||
because it is a **counting** criterion rather than a code-path one. It also reconciles the three
|
||
lanes without special pleading:
|
||
|
||
| state | `ResTNm == ''`? | path | outcome set | control |
|
||
|---|---|---|---|---|
|
||
| `turn1-state`, PID 32 (lane L4) | yes | producers A/B, no walk | 1 | (varies — for other reasons; see below) |
|
||
| `turn1-state`, PID 512 (lane L4) | yes | walk, **1 candidate** | 1 | — |
|
||
| `as-turn15 → 16`, PID 32 (lane AS) | yes | not measured | **> 1** (A chose 64, B chose 62) | **varies**, 22 leaves |
|
||
| **`ar-oracle-A-post → 40`, PID 32 (this lane)** | **yes** | **walk, 1 candidate** | **1** | **pick agrees** |
|
||
|
||
**So `ResTNm == ''` is a necessary condition for research exposure, not a sufficient one.** The
|
||
sufficient condition is `|candidates accepted by TryResearchCandidate| > 1`, and that is not readable
|
||
from the pre-turn save — it needs the walk. §5 states the corrected predicate.
|
||
|
||
### 4.5 What actually varies on turn 40, and why it is the warning already on the books
|
||
|
||
The varying decision is **combat resolution**, and resolution 09-08 §6 already carries the warning:
|
||
*"combat turns are not yet known to be cross-process reproducible."* AR added one datum against it —
|
||
a turn-38 encounter auto-resolved peacefully that reproduced across three processes — and explicitly
|
||
declined to treat that as discharging the warning, on the reasoning that "peacefully" probably
|
||
bypasses `RunCombatRound`.
|
||
|
||
**AR was right to decline, and the reason is now measured: `Auto Resolve Peacefully` does not
|
||
bypass combat when the defender is a colony.** The human committed no ships; the *planet* fought,
|
||
`RunCombatRound` ran, and it is per-process. Three processes on the same input produced three
|
||
different kill counts (2 / 1 / — run 1-R gives a third distinct file, `28bbd9b5…`, whose 48-leaf diff
|
||
against run 1-A is again wholly inside `crep`, `Sigma Fleet VII`, `Venkman` and the two `EvMsg`s).
|
||
|
||
> **`Auto Resolve Peacefully` is not a determinism-preserving resolution.** It means "I commit no
|
||
> ships", not "no combat occurs". A procedure that contains a peaceful auto-resolve is reproducible
|
||
> only if the *other* side also has nothing to fight with — which is why AR's turn-38 encounter
|
||
> reproduced and this turn-40 one does not.
|
||
|
||
**One consequence for rule 26 (c), and it is the sharp one.** Rule 26 says a control must agree with
|
||
itself before it exonerates anything. Here the control varies, so nothing on turn 40 can be measured
|
||
off a single run — and the *sub-tree* discipline lane AD used is what saves the turn: `/Sim/RNG`,
|
||
`/Sim/trdmgr` and every player-0 fleet **are** identical across the two processes, so a lane
|
||
measuring the trade half on this turn has a valid sub-tree, and a lane measuring anything downstream
|
||
of Venkman does not.
|
||
|
||
### 4.6 Read next to lane BP's probe 2 — two lanes, one afternoon, the same layer
|
||
|
||
Lane BP's `pinned-seed-rich-turn.md` landed on VM146 while these runs were in flight, and its result
|
||
and this one point at the **same layer of the AI from opposite directions**. Neither lane knew the
|
||
other's answer when it committed its prediction.
|
||
|
||
| | lane BP (probe 2) | lane BQ (probe 1b) |
|
||
|---|---|---|
|
||
| what was held constant | the per-client **seed** (pinned), same process shape | the **save** (identical input, identical `hooks=off` config) |
|
||
| what varied | the process | the **route to the state** — continuation from turn 37 vs load of turn 38 |
|
||
| residue | newly allocated **fleet ids** paired differently with newly formed fleets | a fleet's **move order** issued in one route and not the other |
|
||
| BP's reading | a per-process input that is not the seed; *inferred* to be a pointer-keyed container under ASLR | — |
|
||
|
||
**One datum this lane can hand BP for free, and it is against the ASLR hypothesis as stated.**
|
||
`shim.log` records the image base on every launch, and on VM145 it was **identical in every one of
|
||
the five processes**: `exe base=0x00f40000 (link-time image base 0x00400000, ASLR delta
|
||
+11796480)`. Different pids, different sessions, same base. That does not touch heap addresses —
|
||
BP's residue could still be a heap-pointer-ordered container — but it does mean *exe* ASLR is not
|
||
varying on these guests, so any hypothesis that reaches for image-base randomisation needs to say
|
||
which allocation it means.
|
||
|
||
And the two results are not the same phenomenon: BP's two processes **disagreed** with each other,
|
||
while this lane's two load processes **agreed** with each other and disagreed with the continuation.
|
||
So BP has a per-process input and this lane has a **per-history** input. Both live in the fleet
|
||
layer, and both are open. Probe 3's per-client draw ledger, taken on `ar-oracle-A-pre → 39`
|
||
**twice — once by continuation from turn 37 and once from a load** — is now the single measurement
|
||
that would speak to both.
|
||
|
||
---
|
||
|
||
## 5. Verdicts on the committed predictions
|
||
|
||
| # | prediction | verdict |
|
||
|---|---|---|
|
||
| **P1b** | `ar-oracle-A-pre.sav` + load + one End Turn → `7a8b3d5e…` | **FALSIFIED.** It produces `4c356f59…`, reproducibly, in two fresh processes. 23 leaves apart from AR's continuation; 17 of them one AI fleet that the continuation moved and the load did not |
|
||
| **P1b-aux** | the same run's `(Autosave EndTurn).sav` = `15b99255…` (the input's own hash) | **FALSIFIED by exactly one leaf** — `/CD[1]/NPrvVa`, +5.00. Every other leaf of the pre-turn round trip is byte-exact, so this lands in the fourth branch P1b-aux enumerated: *"the resave is not byte-exact but is behaviourally equivalent"*. **The resave canonicalisation is exonerated as the cause of P1b's failure**, and `determinism-oracle.md`'s "nothing else varies" is corrected (§4.2) |
|
||
| **P1** | the two turn-40 files **differ** | **CONFIRMED** |
|
||
| **P1**, clause: `/Sim/RNG`, `/Sim/trdmgr`, every player-0 fleet identical | **CONFIRMED**, all three |
|
||
| **P1**, clause: difference confined to `Player[32]`'s `TechTree/*`, `ResTNm`, `otch`, `Events`, `turnstats`, `Checksum` | **FALSIFIED.** **Zero** `TechTree` leaves and **zero** `ResTNm` leaves differ. The difference is a combat at Venkman and its consequences |
|
||
| **P1**, clause: every `Player[16]` leaf identical | **FALSIFIED** — twenty of them moved |
|
||
|
||
**The prediction was right for the wrong reason, and that is the result.** P1 said the files would
|
||
differ *because the research pick is exposed*. The files differ, the research pick is **not**
|
||
exposed, and the exposed decision is one the predicate does not mention at all.
|
||
|
||
### 5.1 The predicate, corrected
|
||
|
||
Rule 26 corollary (c) currently reads *"`ResTNm == ''` names a pick turn"*. Measured here:
|
||
|
||
1. **`ResTNm == ''` at turn start is necessary, not sufficient.** It names a turn on which a pick
|
||
will be *made*. Whether that pick is *exposed* is `|candidates| > 1`, and on this state
|
||
`|candidates| = 1` (§4.4, `candidatesTried=1`). A pick with one candidate is a decision with
|
||
outcome set 1 — the resolution's own criterion, satisfied.
|
||
2. **The predicate has a false-positive class that was visible before the run** (§1.4): four NPC
|
||
players carry `ResTNm == ''` on every turn of this lineage, including the turns whose controls
|
||
agree. All four have `NumOwn == 0`. The predicate must be read only for a non-eliminated AI player
|
||
with `NumOwn > 0`.
|
||
3. **The predicate is incomplete on the other side: it has no combat term.** Turn 40 was exposed
|
||
through `RunCombatRound`, and the pre-turn save *does* name the condition — an AI fleet
|
||
(`Sigma Fleet VII`, PID 32) standing at an enemy colony (`Venkman`, PID 16). That is as readable
|
||
from the save as `ResTNm` is, and it belongs in the predicate.
|
||
4. **A fourth term, and it is not a predicate on the save at all: the load boundary.** Turn 39 ran
|
||
one way in a process that had just run turn 38 and another way in a process that loaded turn 38's
|
||
autosave — with both sides reproducible. So the pre-turn save does **not** fully determine the
|
||
next turn's AI fleet-task decisions. Whatever `Zeta Fleet V`'s move order depended on was **not in
|
||
the file**. That is a bigger claim than exposure and it is the one this lane would send back to
|
||
the resolver.
|
||
|
||
---
|
||
|
||
## 6. Coverage, and what was not done (rule 15)
|
||
|
||
* **Two processes per pair, not three.** Rule 26's bar, matching AR's. Run 1-R is a third process on
|
||
the part-1 input but it is instrumented, so it counts as corroboration of *variability*, not as a
|
||
third control.
|
||
* **Rule 19 cannot be run on turn 40, and it is worth saying why.** The `hooks=off` control varies
|
||
here, so an instrumented run agreeing with either arm would be a `1/k` coincidence with `k ≥ 3`
|
||
(rule 26). Run 1-R produced a third distinct file; that is consistent with neutrality and proves
|
||
nothing about it. **No neutrality claim is made for `l4research` on this state.**
|
||
* **The 1b divergence is localised but not explained.** This lane measured *that* the load boundary
|
||
changes an AI fleet-task outcome; it did not identify the input that is missing from the save. That
|
||
needs probe 3's per-client draw ledger with `this` recorded, on `ar-oracle-A-pre → 39`, taken twice
|
||
— once by continuation from turn 37 and once from a load. The site that fires in one and not the
|
||
other is the answer, and the resolution has already queued exactly that instrument.
|
||
* **`|candidates| = 1` is one observation on one turn.** It explains this agreement; it is not a
|
||
claim that the candidate list is usually 1 (lane AS's state clearly had more). Rule 20: do not fit
|
||
a constant to one observation.
|
||
* **The combat was measured, not decoded.** Three kill counts (2, 1, and run 1-R's own) on one
|
||
encounter. No draw site is attributed — `hooks=off` throughout for the two controls, and this lane
|
||
makes no claim about which consumer inside `RunCombatRound` varies.
|
||
* **The `0x0069dbb0` fuse cannot have fired** in any of these runs (earliest fire is 3 turns after
|
||
the load that draws it), so nothing here bears on it in either direction.
|
||
* **`/CD[1]/NPrvVa` is named, not decoded.** Its neighbours (`NPrv`, `NPrvId = 16`) read as a
|
||
per-player provocation record and its behaviour is +5.00 per turn boundary and per load, falling on
|
||
a combat turn. No writer was looked for. It is a one-line watchpoint for whoever wants it (rule 18).
|
||
|
||
---
|
||
|
||
## 7. Artefacts
|
||
|
||
| what | where |
|
||
|---|---|
|
||
| this document | `findings/control-flow/seed-exposure-forward-test.md` |
|
||
| **1b pair**, two fresh `hooks=off` processes, byte-identical | `verify/results/saves/bq/bq-1b{A,B}-{endturn,post}.sav` (`33e30092…` / `4c356f59…`) |
|
||
| **part 1**, two fresh `hooks=off` processes, **differ** | `verify/results/saves/bq/bq-1{A,B}-post.sav` (`56980aa0…` / `b36ac0ec…`), shared `bq-1{A,B}-endturn.sav` (`1a9d937b…`) |
|
||
| producer-gate run (instrumented, `l4research`) | `verify/results/saves/bq/bq-res-post.sav` (`28bbd9b5…`) |
|
||
| **the research record** — `candidatesTried=1 chose='BIO_GrvAdpt'` | `verify/results/shim/bq/bq-res-aiorders.txt` |
|
||
| shim log (install status for all 20 aiprobes + 3 airesearch detours) | `verify/results/shim/bq/bq-res-shim.log` |
|
||
| inputs (unchanged) | `verify/results/saves/ar-oracle-A-{pre,post}.sav` |
|
||
|
||
`verify/results/saves/bq/` is a subdirectory, so it is invisible to the corpus scan
|
||
(`find_saves()` uses a non-recursive `os.listdir` on `*.sav`) and **the coverage ratchet is not
|
||
touched** (rule 27). None of these files should be promoted into the corpus without deciding that
|
||
question deliberately.
|
||
|
||
---
|
||
|
||
## 8. VM145 as left
|
||
|
||
**Hold released. Guest restored and verified byte-for-byte against the as-found snapshot** (§3):
|
||
|
||
```
|
||
SavedGames the same 9 files, every sha256 identical to as-found
|
||
binkw32.dll 15,527,327 B 903527f4a698eea9… (= shimdist-recap, recap-7584bad-20260908T0615Z)
|
||
shim.cfg 0ae410cc72fe1558… hooks=trace (lane R's recapture config)
|
||
game stopped, as found
|
||
```
|
||
|
||
Left in place, all additive: `C:\SOTS\ui\preBQ\` (the as-found SavedGames snapshot),
|
||
`C:\SOTS\ui\bq\` (the two input saves and this lane's outputs), and
|
||
`C:\SOTS\ui\bq{deploy,grab,click}.ps1`. **`click_helper.ps1` is unmodified.**
|
||
|
||
**Four things for the next holder of VM145.**
|
||
|
||
* **Startup is ~2 minutes if you drive it**, confirming lane AR's correction on VM141: `fg` +
|
||
`key {ESC}` ×3 spaced ~2.5 s, then ~90 s, and the main menu is up. Loading a turn-38/39 save is a
|
||
further **3–4 minutes** and is not compressible. Verify both from a screendump; `tools/vmshot.py
|
||
--one 145` is one call and does not touch the guest.
|
||
* **Chained clicks in one `cmd.txt` are unreliable through the Load dialog.** A three-click chain
|
||
(`Load Game` → `Single Player` → `OK`) landed only the first click, twice. **One `bqclick.ps1`
|
||
call per click, with a screenshot between**, is the only thing that worked reliably —
|
||
independent confirmation of lane M's gotcha, on a different guest.
|
||
* **Reset `SavedGames` to exactly one file — the run's input.** The Load dialog then has one row at
|
||
**(400, 262)** and there is nothing to re-derive. `bqdeploy.ps1 -Save <name>` does it, prints the
|
||
input's sha256, and re-verifies the config.
|
||
* **`C:\Windows\system32\cmd.exe` windows appear over the game** as a side effect of the SOTSUI
|
||
scheduled task and will cover the map. `fg` raises the game again; screenshot before believing a
|
||
click landed.
|
||
* **The `Done` pixel test works exactly as documented** and is worth keeping: (233, 673) read
|
||
**(183, 18, 0)** with the Venkman query up and **(0, 0, 0)** on the map (AR's "≈(8,8,8)" — same
|
||
thing, the map is near-black there). `Auto Resolve Peacefully` (667, 641) shows a tooltip and the
|
||
dove fills the centre panel, so the selection is confirmable from a screenshot before `Done`.
|
||
|
||
---
|
||
|
||
## Proposed board rows
|
||
|
||
New rows:
|
||
|
||
```
|
||
| PROBE 1: the load->turn pair is NOT the continuation's - AR's second hash does not survive a load, and the load form is its own reproducible pair | meta | verified | high | 100% | 2026-09-09 | **Lane BQ**, VM145, `findings/control-flow/seed-exposure-forward-test.md`, probe 1b of the 09-09 resolution. Prediction committed before the run (commit be14266): `ar-oracle-A-pre.sav` (Frame 38, `15b99255...`) + LOAD + one End Turn reproduces `7a8b3d5e...`. **FALSIFIED.** It produces `4c356f5916f0e6e4...` (107,732 B), and it produces it in TWO FRESH `hooks=off` PROCESSES BYTE FOR BYTE, at both snapshot points (`(Autosave EndTurn).sav` `33e3009254f5acd1...` in both). So the load->turn procedure AGREES WITH ITSELF and DISAGREES WITH THE CONTINUATION. 23 leaves apart from AR's file and **17 of them are ONE AI FLEET**: `Flt[1570 "Zeta Fleet V"]` (PID 32) enters turn 39 parked at Alpha Centauri with full range; in AR's continuation the AI issued it a move order (FPlan Wpt 320, FtFlg 12->13, LocID 432->0, both ships Range 9.0->7.0) and in BOTH loads it issued nothing. Plus `Sys[432]` NumFlts 0->1 and `Flt[914 "Nu Fleet III"]` HLay True/False. **RULING: `ar-oracle-A-pre.sav -> 7a8b3d5e...` MUST NOT enter determinism-hashes.txt as a load->turn pair.** What IS certified, two processes: `ar-oracle-A-pre.sav -> (load, one End Turn) -> 33e30092.../4c356f59...` - and that is still the standalone's first trade-raid pair (four raiders parked, no encounter). **THE RESAVE CANONICALISATION IS EXONERATED**: the pre-turn round trip is byte-exact but for ONE leaf, `/CD[1]/NPrvVa` (+5.00 across a load). CONSEQUENCE: **the pre-turn save does not fully determine the next turn's AI fleet-task decisions** - something `Zeta Fleet V`'s order depended on is not in the file. Resolver case; probe 3's ledger on `ar-oracle-A-pre -> 39` taken BOTH by continuation and by load names the site |
|
||
```
|
||
|
||
```
|
||
| PROBE 1: turn 40 varies - but NOT by the research pick. `Auto Resolve Peacefully` does NOT bypass combat, and a pick with ONE candidate is not exposed | control-flow | verified | high | 100% | 2026-09-09 | Lane BQ, VM145. `ar-oracle-A-post.sav` (`7a8b3d5e...`, Player[32] `ResTNm == ''`) in two fresh `hooks=off` processes, one End Turn, `Auto Resolve Peacefully` in both. **The files DIFFER** (`56980aa0...` vs `b36ac0ec...`, 144 leaves) - the committed prediction's first clause holds, and so do `/Sim/RNG` identical (2,503-B block byte-equal), `/Sim/trdmgr` identical and every player-0 fleet identical. **THE MECHANISM CLAUSE IS FALSIFIED: ZERO TechTree leaves and ZERO ResTNm leaves differ.** Both processes picked **BIO_GrvAdpt**. The 144 leaves are a COMBAT: the AI's `Sigma Fleet VII` (PID 32) hit player 16's colony Venkman, the human committed no ships, and the PLANET's defences killed 2 raiders in one process and 1 in the other (50 leaves `crep`, 41 the AI fleet, 8 `Sys[224 "Venkman"]`, 20 `Player[16]` - the prediction's "every Player[16] leaf identical" is also FALSIFIED). Both runs completed the SAME two ships (+8848,+8864); only the losses differ (7744+7952 vs 8000). **So `Auto Resolve Peacefully` means "I commit no ships", NOT "no combat occurs" - it is not a determinism-preserving resolution, and resolution 09-08 §6's combat warning is now measured, not just retained.** AR's turn-38 peaceful auto-resolve reproduced because the other side had nothing to fight with. **WHY THE PICK DID NOT VARY - the producer run, `shim.cfg.l4research` already on the guest, no build**: producers A and B were entered once per AI player and BOTH RETURNED NULL for Player[32]; it reached producer C, the candidate walk; `TryResearchCandidate` was offered **ONE** candidate and took it - `airesult sel=1 candidatesTried=1 chose='BIO_GrvAdpt'` - and the `0x006b36e0 & 7` fallback rotation was never reached (FallbackIndex/FallbackArm both 0). **The outcome set is a singleton because the CANDIDATE LIST HAS LENGTH ONE.** Not the producer gate the resolution guessed - a COUNTING criterion, and a better one |
|
||
```
|
||
|
||
```
|
||
| Rule 26 (c) needs four corrections, all measured on one lineage in one session | meta | verified | high | 100% | 2026-09-09 | Lane BQ, from probe 1. (1) **`ResTNm == ''` is NECESSARY, NOT SUFFICIENT** for research exposure: it names a turn on which a pick is MADE; exposure needs `|candidates accepted by TryResearchCandidate| > 1`, and on `ar-oracle-A-post -> 40` it is 1, so the pick agreed across two processes. Lane AS's varying pick (64 vs 62) had a longer list. The sufficient condition is NOT readable from the pre-turn save. (2) **The predicate has a false-positive class, and it was visible BEFORE the run**: four NPC players (528 Alien Menace, 544 Peacekeeper Enforcer, 560 Von Neumann, 576 Independent Colony) carry `ResTNm == ''` on EVERY turn of this lineage INCLUDING the turns whose controls agree; all four have `NumOwn == 0`. Read the predicate only for a non-eliminated AI player with NumOwn > 0. (3) **The predicate has no COMBAT term and needs one** - turn 40 was exposed through `RunCombatRound`, and the pre-turn save names the condition as plainly as it names ResTNm: an AI fleet standing at an enemy colony. (4) **A fourth term is not a predicate on the save at all**: turn 39 ran one way by continuation and another way after a load, BOTH reproducibly, so exposure is a property of (save, procedure, LOAD HISTORY), not of (save, turn). Rule 26 (c)'s instruction "record the pair as (save, procedure, hashes)" was already right and is now load-bearing for a reason it did not anticipate |
|
||
```
|
||
|
||
Edits to existing rows:
|
||
|
||
- **Row 426** (the resolution's row) — append: `PROBE 1 RUN 2026-09-09 (lane BQ, VM145). 1b FALSIFIED: ar-oracle-A-pre + LOAD + one End Turn gives 4c356f59..., not 7a8b3d5e..., reproducibly in two processes - the AI moved Zeta Fleet V in the continuation and not after a load, so the pair may NOT enter determinism-hashes.txt in AR's form; the LOAD form (33e30092.../4c356f59...) is certified instead. The resave canonicalisation is EXONERATED (pre-turn round trip differs in one leaf, /CD[1]/NPrvVa +5.00 per load). Probe 1 CONFIRMED "the files differ" and CONFIRMED /Sim/RNG + /Sim/trdmgr + player-0 fleets identical, but FALSIFIED the mechanism: the research pick AGREED (both chose BIO_GrvAdpt) and the variation is a COMBAT at Venkman. Producer run: producers A and B both returned null, Player[32] reached the CANDIDATE WALK, and candidatesTried=1 - the outcome set is a singleton by COUNT, not by producer gate.`
|
||
- **Row 424** (AR's oracle pair) — append: `LOAD-BOUNDARY SCOPE 2026-09-09 (lane BQ): this pair is certified ONLY as the two-turn continuation from ar-turn37-816raiders.sav. Its second half does NOT survive being reached by load: ar-oracle-A-pre.sav + load + one End Turn gives 4c356f59..., twice, and differs from 7a8b3d5e... in 17 leaves of ONE AI fleet's movement (Zeta Fleet V moved in the continuation, stayed put after a load). Use the load->turn hashes for the standalone.`
|
||
- **Row 62** — `VM145 = FREE (lane BQ released 2026-09-09; guest RESTORED and verified byte-for-byte to as-found: SavedGames = the same 9 files with identical sha256, binkw32.dll = shimdist-recap 15,527,327 B 903527f4..., shim.cfg = 0ae410cc... hooks=trace, game stopped).` Lane BQ left `C:\SOTS\ui\preBQ\` + `C:\SOTS\ui\bq\` + `ui\bq{deploy,grab,click}.ps1`; `click_helper.ps1` unmodified. **GOTCHA (confirms lane AR's startup correction on a second guest): `fg` + `key {ESC}` x3 spaced ~2.5 s then ~90 s puts the main menu up in about TWO minutes; loading a turn-38/39 save is a further 3-4 min and is NOT compressible.** **GOTCHA (confirms lane M on a second guest): chained clicks through the Load dialog DROP - a three-click chain landed only the first click, twice. ONE click per helper call with a screenshot between.** **TIP: reset SavedGames to EXACTLY ONE file (the run's input) and the Load dialog is one row at (400,262) with nothing to re-derive.** **GOTCHA: `C:\Windows\system32\cmd.exe` windows from the SOTSUI task appear OVER the game and cover the map - `fg` raises the game; screenshot before believing a click landed.** **CONFIRMED: the `Done` pixel at (233,673) reads (183,18,0) with a query up and (0,0,0) on the map; `Auto Resolve Peacefully` (667,641) shows a tooltip and fills the centre panel with the dove, so the selection is confirmable from a screenshot before `Done`.**
|
||
- **`determinism-oracle.md` "Recommended canonicalization rule" / row for the oracle** — append: `CORRECTED 2026-09-09 (lane BQ, rule 11): "mask Player.Status and Summary.Checksum; NOTHING ELSE VARIES" is FALSE on ar-oracle-A-pre/post. `--mask resave` leaves ONE leaf standing - `/CD[1]/NPrvVa`, which advances by exactly +5.00 across a load (and per turn boundary), and FALLS on a combat turn. The old rule was derived on three-player early-game saves with an empty CD[1] diplomacy block. Any load->turn comparison must mask it too, or no load->turn run can ever reproduce a continuation's hash.`
|
||
- **Row 326 / the seed rows** — append: `SHARPENED 2026-09-09 (lane BQ): a research pick is exposed only when the CANDIDATE LIST has more than one entry. Measured on ar-oracle-A-post -> 40: Player[32] entered with ResTNm == '', producers A and B returned null, the candidate walk ran, `candidatesTried=1`, and the pick AGREED across two fresh processes. `ResTNm == ''` predicts a pick, not a divergence.`
|
||
|