diff --git a/findings/subsystems/roll-parity.md b/findings/subsystems/roll-parity.md index cb9f126..c645967 100644 --- a/findings/subsystems/roll-parity.md +++ b/findings/subsystems/roll-parity.md @@ -2,7 +2,7 @@ - **Type:** subsystem (live measurement + static classification) - **Status:** **verified — the answer is NO**, at every scope the question can be asked at -- **Confidence:** high on the negative (measured on two boards, four AI clients, five fresh +- **Confidence:** high on the negative (measured on two boards, three AI clients, six runs in six fresh processes, with the instrument's autosaves byte-identical to the published oracle); medium on the completeness of the site inventory (§6 says what is not covered) - **Owner / date:** lane PAR · 2026-09-08 · VM140 (reference) + VM145 @@ -16,11 +16,11 @@ --- -## 0. The verdict, at four scopes +## 0. The verdict, at five scopes **The hypothesis is false, and it is false in the strongest available way: it fails at the -primitive, at the site, at the client and at the turn.** There is no scope at which an AI client's -word count is fixed. +primitive, at the site, at the client, at the turn, and even at the point where the turn begins.** +There is no scope at which an AI client's word count is fixed. | scope | claim | measured | |---|---|---| @@ -28,6 +28,7 @@ word count is fixed. | **per client, across turns** | one client costs the same each turn | client 32: **3** on turn 2, **7** on turn 1 | | **per client, across processes (path fixed)** | one client's count is a property of the board | client 512, turn 1, **one and the same `cl_RandRange` call** (the research tie-break, `0x006a8495`): **1 word** in one process, **3 words** in another | | **per site** | a site that is reached always costs the same | `RNG_Chance` costs **0 words** at `p ≤ 0` and `p ≥ 1`; `RNG_NextInt` is an **unbounded rejection loop** | +| **at the start of the turn** | a client's stream position is a function of the save | client 32 began its turn at block index **9** in one process and **11** in another, from the same file | The two shadow empires (496, 512) own nothing at all — no colonies, no fleets, no systems — and they still do not agree with each other: on turn 1, 496 spends **0** and 512 spends **1 call @@ -365,11 +366,20 @@ Listed so a later lane does not double-count them: as a 0/1/2 selector, while the four real `AIObject` sinks read `[pkt+0]` as the code — and none of those four draws anything.)* -The load-time cost is large and asymmetric. Measured with the lifetime census on the canonical pair: -the three AI clients arrive at their first turn already **17, 424 and 427** words into their -streams, and the human client's generator is at 0. `g_GlobalRNG 0x00af6e58` shows **3 words drawn, -one per AI client construction** — a second, independent falsification of -`ai-turn-logic.md` §5.1's "every draw from it returns 0", after lane L1's. +**The load-time cost is large, asymmetric, and itself not fixed.** With the lifetime census on the +canonical pair, the three AI clients arrive at their first turn already **9, 411 and 421** words +into their streams (build `par4`, in which the nested double count is corrected), while the human +client's generator is at word 0. And the figure moves between processes: client 32 began its turn at +block index **9** in one run and **11** in another, because the rejection loops it runs during +Prepare Turn resolve differently under different seeds. + +So the AI's generator position at the start of a turn is **not** a function of the save. Two loads of +the same file put the same client at two different stream offsets. That is a second, independent +reason a reimplementation cannot reach a byte match on an AI empire by counting draws. + +`g_GlobalRNG 0x00af6e58` shows **3 words drawn, one per AI client construction** — a second, +independent falsification of `ai-turn-logic.md` §5.1's "every draw from it returns 0", after lane +L1's, and from a different instrument. ---