34 KiB
Trade-raid gate multiplicity — the tail draws once per qualifying fleet, and B returns without drawing
- Type: control-flow (full static decode of the callee + live measurement)
- Status: verified for the multiplicity claim and for
B's zero cost on sector 832; not run for the sector-816 reachability probe (§6 says why, with the numbers) - Confidence: high on the counts (two turns, one process, reproduced turn-to-turn; the control agrees bit-for-bit on the sub-tree the measurement reads — §5)
- Owner / date: lane AD · 2026-09-08 · guest VM141 (
sots-re-win10-b, 192.168.10.143) - Instrument: lane Z's return-address ledger (
draw_sites) + lane H's entry probes atprobes=8— the byte-neutral set. Notprobes=11. Shim buildad-0c6d0a3-20260909T0159Z, configsrc/shim/shim.cfg.hp8unmodified. - Follows:
findings/resolutions/2026-09-09-tail-draws.md§4; lane AC'sfindings/control-flow/trade-raid-rng-gate.md; lane AG'sfindings/control-flow/gate-indexed-rng-audit.md§3.3
0. Headline
The trade-raid roll is per fleet, not per sector, and the word cost scales linearly. With two permitted raiders parked on sector 6 instead of lane AC's one,
TradeManager::Slot13RngCalleeAis entered 2× per End Turn andStrategyServer::OnAllCombatDone_Tailcosts 2 strategic words — against AC's 1 and 1 on the same lineage, the same guest and the same build. Reproduced on two consecutive turns. The return-address ledger prices the site exactly:0x00820e18, calls = 2, words = 2, on both turns. H-sector is dead.
And
Slot13RngCalleeBfired once, at zero words — a second, independent confirmation of lane AG's §3.3 diagnosis.RNG_NextInthas no zero-bound early-out, so aBthat costs nothing never reached its target pick. On sector 832 that is the candidate list being empty, and my two-fleet state reproduces it with a fleet lane AC never had.
There is no oracle pair for this state, and I am not going to pretend otherwise (rule 26). Two
hooks=offruns in two fresh processes produced different post-turn autosaves — 94 leaves apart. But the difference is entirely the AI empire's design/build/fleet decisions, and/Sim/RNG,/Sim/trdmgrand every player-0 fleet are bit-identical across all three processes, instrumented and not. §5 gives the digests. Every number in §3 is read off that reproducible sub-tree; none of them is read off a leaf that moved.
1. Predictions, committed before the build (rule 2)
Committed in d98f435 before the shim was built, before the workload was played and before any
counter was read. Reproduced verbatim below with the verdicts added.
1.0 The callee, decoded in full first
Lane AC read the caller and reported the short-circuit inside the callee from a partial read. This
lane decompiled the whole of TradeManager::Slot13RngCalleeA 0x00820ca0 (436 bytes, 89 decompiled
lines, loop and converge point both visible — rule 4), because the prediction depends on where the
draw sits relative to the loop:
A(fleet, freighterInSector) -> bool:
if fleet == null: return false # 0 words
n = (fleet+0xa8 - fleet+0xa4) / 4 # ship vector count
if n <= 0: return false # 0 words
anyBig = OR over ships of ( *(design + 0x12c) > 1 )
allSuppressed= AND over ships of ( ship+0x18 & 0x80 )
nDE = #{ ships : !(flags & 0x80) and *(design+0x12c) == 0 }
nCR = #{ ships : !(flags & 0x80) and *(design+0x12c) == 1 }
bestScale = max over ships of ( (flags & 0x100000) ? K : 1.0 )
if anyBig: return TRUE # 0 words <-- short-circuit
if allSuppressed: return false # 0 words
odds = (nCR >= 1 ? ODDS_CR : (nDE > 0 ? ODDS_DE : 0.0)) + (nCR + nDE) * PER_SHIP
if freighterInSector: odds = odds + odds
r = NextFloat() # <-- EXACTLY ONE WORD
return (odds * bestScale > r)
Three consequences the measurement was against:
- The draw is inside the callee and the callee is called once per fleet, so the site's cost is
Σ over fleets passing G0–G4, not a per-sector constant. design + 0x12ctakes values 0, 1 and >1 and buckets ships into two counted classes plus a third that short-circuits — a hull class field. AC'sRepair and Salvage(IND_CruisCon) is the== 1bucket, so> 1is a hull above cruiser.- There is exactly one
NextFloaton the path with no rejection loop, so a fleet that reaches the roll costs exactly one word — never two.
The constants, read out of the image afterwards (rule 23 — read the four bytes, and these are all widened floats, not decimals):
| symbol | address | bytes | value |
|---|---|---|---|
ODDS_CR |
0x009e20d8 |
00 00 00 A0 99 99 C9 3F |
(double)0.2f = 0.20000000298023224 |
ODDS_DE |
0x009e5060 |
00 00 00 A0 99 99 A9 3F |
(double)0.05f = 0.05000000074505806 |
PER_SHIP |
0x009e31c0 |
00 00 00 40 E1 7A 84 3F |
(double)0.01f = 0.009999999776482582 |
K (flag 0x100000) |
0x009f8d48 |
C3 F5 A8 3E |
float 0.33 — it reduces the odds |
This confirms AC's 0.20 / 0.05 / +0.01·nShips read for this function (AC quoted the same two
decimals for GenerateTradeRaidEncounters, a different site; they happen to agree) and adds the
per-ship scale, which had not been valued. A one-cruiser fleet's odds are
0.20000000298023224 + 0.009999999776482582 = 0.21000000275671482, times 1.0, not doubled —
sector 832 holds no freighter.
1.1 The state, read from the save before touching the guest
verify/results/saves/ac-turn22-raider.sav: player 0 re, PlyrIdx 0, HomeSys 48,
Sav 63,032,174, CnRad true; exactly one player-0 fleet (FltID 3744 "Alpha Fleet",
NShips 1, LocID 832, Pos [0, 0, 8.0], FtFlg 4, DesID 17); sector 6 = TradeID 832,
tsgridID 6, Pos [0, 0, 8.0], tssec 0, tsct 0, tscr 253, tsnumsys 4,
tsnumflt 1; all six sectors tscr 253.
The workload built: one more Repair and Salvage cruiser at system 48, kept as its own fleet,
ordered to the sector-6 node — two single-cruiser fleets on one sector.
Deliberate deviation from the brief, stated up front. The brief and resolution §4 asked for a
second raider of a hull satisfying design+0x12c > 1, to price the short-circuit. §1.0 shows that
field is a hull class and > 1 means a hull above cruiser. The Build screen's Dreadnought category
is empty in this game (screenshot b4), so no such hull exists to build, and pricing the
short-circuit is the second question anyway. A second cruiser answers the first with the
cleanest signal: under H-fleet the word count doubles, under H-sector it does not move. The
short-circuit stays unpriced — recorded as a gap in §7, not skipped.
1.2–1.8 The predictions, with verdicts
| # | prediction | verdict |
|---|---|---|
| P1 | H-fleet: with two single-cruiser fleets, Slot13RngCalleeA entered 2×/turn and the tail costs 2 words/turn |
CONFIRMED, both turns (§3) |
| P2 | H-sector: A entered 1×, tail 1 word regardless of fleet count |
FALSIFIED — as intended; this is the hypothesis the lane existed to kill |
| P3 | draw_sites shows exactly one strategic row inside the callee body, NextFloat, ret_rva in 0x00420ca0..0x00420e53, calls == words == 2, no_draw_calls == 0, and the site sum equals the boundary ledger's tail delta |
CONFIRMED exactly — row at call 0x00820e18, calls 2, words 2, both turns; bracket residual 0 |
| P4 | B entered once per succeeding fleet (0–2×/turn) and costs 0 words — no strategic row in 0x0048b440..0x0048b976 |
CONFIRMED as a number, and its meaning was wrong in my brief. B entered 1× / 0× on the two turns and cost 0 words both times. Lane AG (posted after this prediction was committed) read all 139 bytes of RNG_NextInt and found no zero-bound early-out, so B cannot reach its pick without spending a word. B costing 0 therefore proves B returned before the pick — it is not a cheap success, it is a non-success. My predicted number was right for the wrong reason and I am recording that plainly. |
| P5 | two hooks=off runs in two fresh processes give byte-identical autosaves |
FALSIFIED. I flagged it as the most likely failure and it failed. §5. |
| P6 | the probes=8 post-turn autosave is byte-identical to the hooks=off oracle |
Unanswerable as stated (P5 failed, so there is no oracle to compare to), and answered in a better form: the instrumented run and both control runs are bit-identical on every sub-tree except the AI's decisions. §5. |
| P8 | if A reads 0, name the failed conjunct from the save |
not triggered; the conjuncts were read anyway (§4) |
2. What was run
Four fresh processes on VM141, all with the same guest, the same dist
(C:\SOTS\shimdist-ad, BUILD_ID ad-0c6d0a3-20260909T0159Z, built in
/srv/re-lab/build/sots-engine-ad after rm -rf of the tree and with no local build* shipped —
rule 24) and the same input save.
| run | config | End Turns | purpose |
|---|---|---|---|
| play-forward | shim.cfg.hoff |
4 (turn 23 → 27) | build the workload |
| R1 | shim.cfg.hp8 (probes=8) |
2 (turn 27 → 29) | the measurement |
| OA | shim.cfg.hoff |
1 (turn 27 → 28) | control |
| OB | shim.cfg.hoff |
1 (turn 27 → 28) | control, second fresh process |
Input save ad-turn27-two-raiders.sav, sha256
1c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436. It is the post-turn autosave of
turn 26, produced by ordinary play from ac-turn22-raider.sav: queue two CR Repair and Salvage,
End Turn ×2, form the first completed hull into Beta Fleet, Move → sector-6 node, End Turn ×2.
Instrument armed and verified from shim.log, not assumed: all seven drawsite: detours
create=MH_OK enable=MH_OK; probe: installing 8 of 12 (probes= in shim.cfg) and all eight
create=MH_OK enable=MH_OK. Probe indices 8–11 report NOT INSTALLED, never 0 (rule 1) — index 8
is GenerateTradeRaidEncounters, the detour lane H bisected as not byte-neutral, and it is
excluded by construction.
The gate, read from the save for the measured turns (rule 28 — the field values, not a summary). From R1's own post-turn autosave at turn 29:
| conjunct | field | value |
|---|---|---|
G2 fleet at a TradeSector node |
Flt["Alpha Fleet"].LocID / Flt["Beta Fleet"].LocID |
832 / 832 |
| G3b owner's bit in the raid mask | Trade[832].tscr |
253 = 0b11111101, bit 0 = player 0 ✓ |
G3c FtFlg & 0x800 armed? |
Trade[832].tsct |
0 → not armed; neither fleet carries 0x800 (FtFlg 4 and 4) |
G4 arrived, Pos bit-equal |
Flt.Pos vs Trade[832].Pos |
both [0, 0, 8.0], bit-identical |
| — | Trade[832].tsnumflt / tsflt |
2 / 3744, 6544 |
3. The numbers
3.1 Entry counts (probes=8, R1)
| probe | turn 28 | turn 29 | lane AC, one raider |
|---|---|---|---|
ServerSpyManager::vslot13 |
1 | 1 | 1 |
ServerSpyManager::vslot14 |
1 | 1 | 1 |
ServerTradeManagerImpl::vslot13 |
1 | 1 | 1 |
ServerTradeManagerImpl::vslot15 |
1 | 1 | 1 |
SpyManager::Slot13RngCallee |
0 | 0 | 0 |
TradeManager::Slot13RngCalleeA |
2 | 2 | 1 |
TradeManager::Slot13RngCalleeB |
1 | 0 | 1 then 0 |
ServerTradeManager::CreateRaidEncounter |
1 | 2 | 0 then 1 |
| indices 8–11 | NOT INSTALLED | NOT INSTALLED | — |
vslot13 is still entered once per turn while A is entered twice: the multiplicity is
inside the callee's caller loop over the fleet vector, exactly as AC read it. That is the cleanest
possible separation of H-fleet from H-sector — one instrument row moves, the other does not.
3.2 The boundary ledger
turn 28 BeginProcessTurn 575 -> 575 delta 0
ProcessTurn 575 -> 593 delta 20
OnAllCombatDone_Tail 593 -> 595 delta 2
BRACKET total 22 attributed 22 residual 0
turn 29 BeginProcessTurn 595 -> 595 delta 0
ProcessTurn 595 -> 615 delta 20
OnAllCombatDone_Tail 615 -> 617 delta 2
Two words per turn in the tail, on both turns. Lane AC's control (no raider) was 0; AC's active state (one raider) was 1; two raiders give 2. The bracket residual is 0 on turn 28, so nothing else moved.
3.3 Per-site attribution by return address (draw_sites)
Turn 28, strategic rows only (helper-internal rows and other generators elided; the report tool marks them):
* NextFloat call 0x0050329d calls= 1 words= 1
* Chance call 0x00753d87 calls=14 words= 0
* NextInt call 0x007929a4 calls= 1 words= 1
* NextFloat call 0x00820e18 <-- the raid roll calls= 2 words= 2
* Chance call 0x00893426 GenerateTradeRaidEncounters calls= 8 words= 8
* Chance call 0x00893513 GenerateTradeRaidEncounters calls= 8 words= 8
=> attributed strategic words: 20
Turn 29 is the same plus ProcessResearch+0x1c8 (1 word) and a NextFloat at call 0x0088df4f
(1 word) — two sites inside ProcessTurn, not the tail; 0x00820e18 is again calls = 2, words = 2.
0x00820e18 is lane V2's site, listed in indirect-edges.md §3.1 as trade slot 13's NextFloat,
fired once by lane AC and now priced at one word per qualifying fleet.
No strategic row anywhere in 0x0088b440..0x0088b976 on either turn, and none in
ServerTradeManager::CreateRaidEncounter's body on the turn it ran twice. So B cost 0 and
CreateRaidEncounter cost 0 — both by return-address attribution, not by a word count that could
have hidden them.
3.4 The odds arithmetic, first measured support
Two fleets × two turns = four fleet-rolls at p = 0.21000000275671482 (one cruiser, no
freighter in sector 832, bestScale 1.0). Expected successes 0.84; observed 1 (turn 28's single
B entry). Lane AC's two rolls at the same p gave 1. Six rolls, two successes, expectation 1.26 —
consistent, and stated as consistency rather than validation: six Bernoulli trials cannot
distinguish 0.21 from 0.15 or 0.30.
4. What this settles about Slot13RngCalleeB — a verdict on lane AG §3.3
Lane AG's §3.3 posted while this lane was measuring. Two of its results bear directly on my numbers:
RNG_NextInt(0x004271c0) has no zero-bound early-out. A single-candidate list still costs one word.FUN_00820af0, called at0x0088b62cright after the pick, draws again at0x00820c1b.
So a B that costs 0 words did not reach 0x0088b613. My turn 28 has B entered once and the
tail's whole cost accounted for by A's two words — B returned before its pick, on a fleet lane
AC never had, on the same sector. That is an independent reproduction of AG's diagnosis rather
than a re-reading of AC's single observation.
Which conjunct failed, from the save. trdmgr at turn 27 and again at turn 29 holds three
route records, trfr = 18, 14, 14 (tro = 32, the AI, on all three). Resolving each source system
to the sector whose node it sits nearest: system 18 (Ko'Kotan, [9.56, 0.06, 2.27]) → sector
816 at 2.20 ly; system 14 (Ko'Graapa, [1.44, 1.42, -2.22]) → sector 768 at 2.03 ly.
No route is sourced in sector 832. So G_B1b (containingSector[rt->trfr] == sector) rejects
all three routes and the candidate list is empty — G_B4.
What my run does not settle, and I want this said clearly. AG flagged one unproven reading:
that TradeManager+0x0c is a per-system "containing trade sector" table, versus a
sector-indexed vector of six, in which case trfr ∈ {14, 18} fails the bounds check G_B1a and
0x0088b613 is unreachable in principle. My measurement cannot distinguish those two readings,
because on sector 832 both of them predict exactly what I saw: B entered, B returns before the
draw. The experiment that separates them is a raider parked on a sector that does source a route,
and §6 explains why this game cannot produce one without further engineering.
5. The control — rule 26, honestly
The hooks=off control does not agree with itself. Two fresh processes, same guest, same build,
same input save, one End Turn each:
input ad-turn27-two-raiders.sav 1c8baa27680809d585ab1728391e82729642d32aaedffd5bf95b616f0a11a436
OA (Autosave EndTurn).sav 16f63adbf383946db17c381998957172bca803406b7df78f3b03805fef0bbcb8
(Autosave).sav a634510e7208cceb10d8ce016ceb0153601f11d7291f08122bcdb6418e313331
OB (Autosave EndTurn).sav 16f63adbf383946db17c381998957172bca803406b7df78f3b03805fef0bbcb8
(Autosave).sav 676b1778880b5d4784ba7f6ef48b1a8e56745adab70a815943b7744876686260
R1 (probes=8) turn 28 pre 16f63adbf383946db17c381998957172bca803406b7df78f3b03805fef0bbcb8
turn 28 post 01d6367e051cec539a9266b95b5f41cd1d6434bc8c100c96e8008fc59268da9c
turn 29 pre 5b5618ad1557ae346dc1624ccea38485e3afac967134c7517b17a50dbc88a807
turn 29 post bf6eec6d4a70a3a6d80baf8df12d6f1cc87ad66d948233adcc7a259d829c4248
The pre-turn autosave is byte-identical in all three processes and across both configurations —
the load path is deterministic and the instrument does not touch it. The post-turn autosave is
different in all three. So there is no oracle pair for this state and no rung-A calibration pair
came out of this lane (rule 26: a control that varies exonerates nothing, and one instrumented run
agreeing with one control run would be a 1/k coincidence, not evidence).
But the variation is localised, and it is not where the measurement lives. The state-checksum
tool (--floats bits --mask none) on OA vs OB reports 94 leaf differences, and on R1 vs OA the
same 94, of the same shape:
| where | leaves |
|---|---|
Player[32 "The Eternal Empire"] — ShipRecs, odes, designs, Sav, Maint, PvSav, FNGNum |
41 |
AI fleets (Sigma/Tau/Upsilon/Phi/Chi/Psi Fleet VI, ids and Pos/FtOrig/FPlan) |
~35 |
AI build queues (Sys[368]/BQ, Sys[272]/BQ) |
4 |
turnstats/history rows for player 32 |
4 |
/Sim/ModCount, /Sim/NumFlts, /Sim/DesignIDs[], /Sim/FleetIDs[], /Sim/ShipIDs[], /Summary/Checksum |
6 |
Every one of them is the AI empire deciding differently — the per-process AI seed rule 26 pinned on
turn1-state, at turn 27 with a much larger AI. Nothing else moves. The digests that matter,
printed by state_checksum.py --tree, are bit-identical in all three post-turn saves:
/Sim/RNG 1e458a997f51bbdf (the serialised strategic generator, 2503 B)
/Sim/trdmgr 89643da6fabb386b (all six trade sectors and all three route records, 180 leaves)
and there is no leaf under any trade sector, no trdmgr leaf, and no player-0 fleet leaf in
either diff.
So the defensible statement, which is weaker than an oracle pair and much stronger than nothing:
Three fresh processes — two un-instrumented, one carrying the full
probes=8+draw_sites+ boundary-ledger instrument — agree bit-for-bit on the strategic generator's serialised state, on the entire trade manager, and on every fleet this measurement is about. They disagree only on the AI empire's design and build choices.
That is a rule-19 result as well as a rule-26 one: on this state the instrument is
behaviour-neutral on every leaf outside the AI-decision sub-tree, including the generator itself.
It does not license calling ad-turn27-two-raiders.sav a calibration pair, and I am not proposing
it as one.
What would make one. The variation is a client AI decision, and --turn-commands replay runs
no AI (command_replay.h:83). A Rung-B pair captured from this state with the command stream
recorded should be reproducible even though the Rung-A pair is not — that is a cheap, concrete next
step for whoever owns the standalone, and it is the only way this state becomes calibration data.
6. The sector-816 probe the coordinator asked for — named, costed, not run
Mid-lane the coordinator redirected: move the raider from sector 6 (TradeID 832) to sector 5
(TradeID 816), which does source routes, so B can reach 0x0088b613. That is the right
experiment and I did not run it. The reason is geometric and it is worth writing down, because it is
not obvious from the saves and it will otherwise cost the next lane the same hour.
Every sector that sources a route is out of range of this empire. Trade-sector node positions
and my two colonies, from ad-turn27-two-raiders.sav; the hull range of every cruiser I can build
is 9.0 ly, and the fleet panel's Range: 4.0 (4.0) on the raiders at sector 6 confirms range is
consumed cumulatively from the last supply point:
| sector | sources a route at turn 27? | from Epsilon Eridani (idx 0, home) | from Downbelow (idx 12, my only other colony) |
|---|---|---|---|
| 752 | no | 12.85 | 8.43 |
| 768 | yes (trfr 14, ×2) |
11.53 | 10.14 |
| 784 | no | 9.36 | 3.49 |
| 800 | no | 9.37 | 11.77 |
| 816 | yes (trfr 18) |
15.66 | 12.12 |
| 832 | no | 4.99 | 4.56 |
The two in-range sectors (832 at 4.56, 784 at 3.49) source nothing; the two that source routes are 10.14 and 12.12 ly away against a 9.0 ly hull. Confirmed from the UI as well: with Trade View on, only sector 6's cube is drawn on the map at any zoom, so no other sector node is even a clickable move target from where this empire stands.
The workload that would reach it, costed from the Build screen. The player's stock
Extended Range destroyer has Range 27.0, construction cost 2,252, node speed 4.0
(screenshot s9). One of those, built at Epsilon Eridani, reaches sector 816's node (15.66 ly, ~4
turns at node speed 4.0) or sector 768's (11.53 ly, ~3 turns). Build is ~1–2 turns at this colony's
3,985/turn ship-construction budget. So the probe is ~6 turns of play from
ad-turn27-two-raiders.sav, and it needs nothing that is not already unlocked.
Two warnings for whoever runs it, both from arithmetic rather than opinion:
- A destroyer takes the
nDEbranch:odds = 0.05000000074505806 + 0.009999999776482582 = 0.06, doubled to 0.12 if sector 816's AIFreightersfleet satisfiesfreighterInSector. That is a 1-in-8 chance per fleet per turn ofAsucceeding, andBonly runs on a success. At 0.12, four turns with one fleet is a 40% chance of ever seeingB— send several fleets, or expect to measure a lot of turns. A cruiser would be 0.21 (0.42 doubled) but cannot get there; a custom cruiser design carrying theExtended Rangemission section would fix that, at the cost of driving the Design screen. - Sector 816's
tsctis 2 — bit 1, the AI's index, not mine — soTradeSector_PlayerTradesHereis false for player 0 and noFtFlg & 0x800is required, exactly as on sector 832.tscris 253 there too. The gate is otherwise identical; onlyG_B1bchanges.
Corpus count for the sector-816 predicate: still 0 of 22. Nothing here changes that, and my zero
on 0x0088b613 is a zero on sector 832, where G_B1b provably fails — it is not a zero on the
predicate AG named.
7. Coverage and what was not done (rule 15)
- Two instrumented turns, one process, two fleets, one sector, one ship per fleet, one hull
class. The multiplicity claim rests on 1 → 2, not on a curve. A third fleet was built and was
sitting at the home system throughout (
Gamma Fleet,LocID 48); ordering it to sector 6 and re-measuring would give the 3-point curve cheaply and was not done. - The
design+0x12c > 1short-circuit is still unpriced. The Dreadnought category is empty in this game, so no such hull exists to build. It stays a static read. B's innerNextInt(0x0088b613) andFUN_00820af0'sNextFloat(0x00820c1b) are still unfired, here as everywhere. §6 is the recipe.- The freighter doubling is untested. Sector 832 has no freighter, so
param_2was false on every roll this lane took, and theodds + oddsbranch was never entered. bestScalewas 1.0 on every roll — no ship carried flag0x100000, so the 0.33 multiplier is a static read only.- The spy half is untouched, as instructed.
- One accidental UI action, disclosed: during the sector-816 feasibility check I mis-clicked the
savings/research slider on the map panel in a throw-away
hooks=offsession. That session was discarded and no save used in §3 or §5 descends from it — R1, OA and OB all loadad-turn27-two-raiders.savfrom disk in a fresh process. - No probe wanted
probes=11. Nothing in this lane needed an index above 7; the four uninstalled rows are reported as NOT INSTALLED and never as zeros.
8. Artifacts
| what | where |
|---|---|
| input state, two raiders on sector 6, turn 27 | verify/results/saves/ad-turn27-two-raiders.sav |
probes=8 trace, two instrumented End Turns |
verify/traces/ad-r1-turn28-turn29.jsonl |
| shim log for R1 (probe/drawsite install status) | verify/results/shim/ad/ad-r1-shim.log |
control autosaves, two fresh hooks=off processes |
verify/results/saves/ad-oracle-{A,B}-post.sav |
| leaf-level diff of the two controls | verify/results/state-checksum/ad-oracleA-vs-oracleB.txt |
| instrument | sots-engine src/shim/shim.cfg.hp8, unchanged; build ad-0c6d0a3-20260909T0159Z |
| build tree | CT111 /srv/re-lab/build/sots-engine-ad (rm -rf'd before the build; dist /srv/re-lab/shim/dist-ad) |
New content for the coverage ratchet (rule 27): nothing new in kind — the same CnRad,
tscr = 253 and non-star Flt.LocID lane AC's saves already carry, now with two fleets at one
sector node and tsnumflt = 2 naming both.
9. VM141 as left
Guest restored and the hold released. The game is stopped; C:\SOTS\shim.cfg is
shim.cfg.hoff; C:\SOTS\binkw32.dll is this lane's build; C:\SOTS\SavedGames is back to the
13-file set lane AC left (byte-identical, verified by sha256 against
C:\SOTS\SavedGames-adstash, which has been removed) plus ad-turn27-two-raiders.sav, so
Load-dialog row positions have moved again — screenshot the dialog, do not reuse a remembered
row. Left in place, all additive and harmless: C:\SOTS\shimdist-ad, C:\SOTS\ui\ad-*.ps1
(ad-go.ps1 takes -Cfg, ad-ui.ps1 writes cmd.txt and runs the helper once) and this lane's
intermediate saves and traces under C:\SOTS\ui\ad-*. click_helper.ps1 is unmodified from lane
AC's version.
Two things that cost this lane time, for the next holder:
- Startup is ~4½ minutes on this guest, not 60 seconds, and the intro is three separate movies.
qm sendkey 141 escskips them but only once the movie has focus; the reliable form is the click helper'sfg+key {ESC}repeated three times, then wait ~90 s more for the main menu. Loading a turn-27 save is a further 3–4 minutes. Budget ~9 minutes per run before the first End Turn, and screenshot at every step — a QMPscreendump ... -f pngis fresh and cheap. - The
End Turnclick after leaving Move mode is swallowed once. The first click exits the mode; the turn only starts on the second. Screenshot for the progress bar rather than assuming.
Proposed board rows
New row:
| The trade-raid roll is PER FLEET: 2 raiders on one sector = 2 entries, 2 words; B returns without drawing | control-flow | verified | high | 100% | 2026-09-08 | Lane AD, VM141, `findings/control-flow/raid-gate-multiplicity.md`. Two single-cruiser fleets parked on sector 6 (TradeID 832) from ac-turn22-raider.sav: `TradeManager::Slot13RngCalleeA` entered **2x** per End Turn on BOTH measured turns against lane AC's 1, `OnAllCombatDone_Tail` costs **2** words against AC's 1, and the return-address ledger prices the site exactly - 0x00820e18 calls=2 words=2, bracket residual 0. H-sector (one roll per sector) is DEAD; the cost is `sum over qualifying fleets`. `vslot13` is still entered ONCE per turn, so the multiplicity is the caller's loop over StrategyServer+0x64, exactly as AC read it. Instrument `probes=8` (the byte-neutral set - NOT 11), shim `ad-0c6d0a3-20260909T0159Z`, cfg shim.cfg.hp8 unmodified, own build dir /srv/re-lab/build/sots-engine-ad rm -rf'd first. CONSTANTS READ FROM THE IMAGE (rule 23, all WIDENED FLOATS): ODDS_CR 0x009e20d8 = (double)0.2f, ODDS_DE 0x009e5060 = (double)0.05f, PER_SHIP 0x009e31c0 = (double)0.01f, and a per-ship scale 0x009f8d48 = 0.33f that REDUCES the odds when ship+0x18 & 0x100000. One-cruiser fleet odds = 0.21000000275671482; six rolls across AC+AD gave two successes (expectation 1.26) - consistent, not validated. `Slot13RngCalleeB` entered 1x on turn 28 and cost **0 words** by return-address attribution - and lane AG's reading that RNG_NextInt has NO zero-bound early-out turns that into a PROOF that B returned before its target pick, i.e. the candidate list was empty (G_B4), reproduced with a fleet AC never had. trdmgr holds 3 routes, trfr 18/14/14, sourced in sectors 816 and 768 - NONE in 832 |
| NO ORACLE PAIR for the turn-27 raider state - the control varies, but ONLY in the AI's decisions, and /Sim/RNG is bit-identical across three processes | meta | verified | high | 100% | 2026-09-08 | Lane AD (rule 26). Two `hooks=off` runs of one End Turn from ad-turn27-two-raiders.sav in two fresh processes gave DIFFERENT post-turn autosaves (a634510e / 676b1778); the pre-turn autosave is byte-identical in all three processes (16f63adb), so the load path is deterministic and the divergence is inside the turn. So NO rung-A calibration pair came out of this state and none is proposed. BUT the state-checksum localises the variation completely: 94 leaves, ALL of them Player[32 "The Eternal Empire"] designs/ShipRecs/odes/build queues/fleet ids and positions, plus ModCount, NumFlts, the three id lists and Summary.Checksum. `/Sim/RNG` = 1e458a997f51bbdf and `/Sim/trdmgr` = 89643da6fabb386b in ALL THREE post-turn saves (two hooks=off and one probes=8), and NO trade-sector, trdmgr or player-0 fleet leaf appears in either diff. Two consequences: (a) every number lane AD reports is read off a sub-tree the control reproduces bit-for-bit; (b) RULE 19, on this state: the probes=8 + draw_sites + boundary-ledger instrument is behaviour-neutral on every leaf OUTSIDE the AI-decision sub-tree, including the serialised strategic generator. The named next step is a RUNG B pair - `--turn-commands` replay runs no AI, so a captured command stream should make this state reproducible where Rung A cannot |
| Sector 816 is UNREACHABLE from lane AC's empire - the AG probe needs a 27 ly hull, and one is already buildable | control-flow | verified | high | 100% | 2026-09-08 | Lane AD, measured from ad-turn27-two-raiders.sav geometry + the Build screen. Node distances from the human's only two colonies (Epsilon Eridani idx 0, Downbelow idx 12) against a 9.0 ly cruiser range: sector 816 = 15.66 / 12.12, sector 768 = 11.53 / 10.14, sector 752 = 12.85 / 8.43, sector 800 = 9.37 / 11.77, sector 784 = 9.36 / 3.49, sector 832 = 4.99 / 4.56. The only two sectors IN range (832, 784) source no route; the only two that source routes (816 via trfr 18, 768 via trfr 14 x2) are out of range. With Trade View on, only sector 6's cube renders at any zoom, so no other sector node is even a clickable move target. THE FIX IS ALREADY UNLOCKED: the stock `Extended Range` DESTROYER has Range 27.0, construction cost 2,252, node speed 4.0 - ~1-2 turns to build, ~4 turns to sector 816's node, so AG's probe is ~6 turns of play and needs no research. TWO WARNINGS: a destroyer takes the nDE odds branch, 0.05f + 0.01f = 0.06 (0.12 if the AI Freighters fleet in 816 satisfies the doubling), i.e. a 1-in-8 success per fleet per turn - send several fleets or measure many turns; and sector 816's tsct = 2 is the AI's bit, not player 0's, so no FtFlg & 0x800 is required there, exactly as on 832 |
Edits to existing rows:
- Row 62 (guest holders) —
VM141 = FREE (lane AD released 2026-09-08; guest restored, SavedGames back to AC's 13-file set byte-identical PLUS ad-turn27-two-raiders.sav, so Load-dialog rows have moved AGAIN - screenshot the dialog. Lane AD left C:\SOTS\shimdist-ad + C:\SOTS\ui\ad-*.ps1; click_helper.ps1 unmodified. GOTCHA: startup on this guest is ~4.5 min through THREE intro movies (fg + key {ESC} x3 via the click helper, then ~90 s), and loading a turn-27 save is a further 3-4 min - budget ~9 min per run before the first End Turn. GOTCHA: the first End Turn click after leaving Move mode is swallowed exiting the mode; the turn starts on the second click.) - Row 207 — append:
PRICED 2026-09-08 (lane AD): 0x00820e18 costs ONE WORD PER QUALIFYING FLEET, not one per sector - two raiders on one sector give calls=2 words=2. 0x0088b613 (B's NextInt) still UNFIRED and now known to be a proof-carrying zero: RNG_NextInt has no zero-bound early-out (lane AG), so B costing 0 words means B never reached the pick. - Row 399 — append:
Lane AD reproduced AC's B-at-zero-words with a SECOND, independent fleet and read the failed conjunct out of the save: trdmgr's three routes have trfr 18/14/14, sourced in sectors 816 and 768, none in 832 - G_B1b, exactly as lane AG decoded. AD's data does NOT distinguish AG's per-system vs sector-indexed reading of TradeManager+0x0c: on sector 832 both predict the same zero. - Row 186 (
RNG LEDGER CLOSED) — append to the existing qualification:Lane AD 2026-09-08: the tail site's cost is not a constant at all - it is one word per permitted raider parked on a sector node, measured at 2 with two fleets. Any per-turn tail figure is a statement about the fleet count in that state.