sots-re/campaign/board.md
2026-09-08 03:54:10 -04:00

33 KiB

Campaign board

Status flow: backlog → in-progress → mapped → verified (or blocked). verified requires re-verifier evidence. Maintained by re-quartermaster.

Target Type Status Conf Coverage Updated Notes
RTTI class inventory meta mapped high 100% 2026-09-07 findings/objects/00-inventory.md — 1924 types, engine=Mars
.gob format subsystem mapped high 100% 2026-09-07 renamed uncompressed ZIP (community-known)
Mars::AppStartup (entry) control-flow mapped high 100% 2026-09-07 entry 0x00925794 -> WinMain 0x0089dd30 -> DemoApp ctor 0x0089c950 -> Mars::Application::Initialize 0x008a0e50 (config/affinity, D3D9, window, sound thread, OnStartup -> net thread). findings/control-flow/turn-spine.md
main loop / tick dispatch control-flow mapped high 90% 2026-09-07 Application::Run 0x0089f5b0: FrameTimer, PanelManager, DemoApp::OnUpdate 0x00898800 / OnTick 0x0089a640 / OnRender 0x00899210. Turn pipeline: EndTurn 0x00783be0 -> BeginProcessTurn 0x007d98e0 -> StrategyServer::ProcessTurn 0x007dc6c0 -> RunCombatRound 0x007cbe80 -> SETurnResults -> ResumePlaying 0x007ddc90. Lockstep on every machine
Game::ClientPlayer / AIPlayer object verified high 100% 2026-09-07 ServerPlayer confirmed strict vs real saves (turns 1-3)
Game::StarSystem object verified high 100% 2026-09-07 ServerSystem confirmed strict vs real saves; NVO.indi unconditional; haltv bool; cp1252 names
Game::Planet / DOPlanet object mapped high 100% 2026-09-07 Planet : Actor is a RENDER actor, not streamed; all colony state is in ServerSystem (+PlayerView in NVs map)
Game::ShipDesignDef / DesignList object verified high 90% 2026-09-07 engine game/design merged: rules + stats in C++; 127/127, 197/197 DOpts, gating 121/127 (hidden riders warn), oracle-identical incl. 9,673 stats; 43 unit tests
Game::FleetLayout object verified high 100% 2026-09-07 StarFleet/StarShip confirmed strict vs real saves; PrisonerHold PrNSp gated on PrMax>0
Mars entity chain object mapped high 100% 2026-09-07 EntityBase@0x00a36fd0 (10) -> PhysicalEntity@0x00a3710c (12) -> TargetableEntity -> Actor@0x009e2114 (36); mixins RigidBody/Body/NetworkObject/HandleObject/IScriptable
Game::GameCombatSim + CombatCommand* subsystem backlog — 0% 2026-09-07 tactical combat (~40 command types)
D3D9 device init subsystem backlog — 0% 2026-09-07 Mars::DrawDevice/Camera → Direct3DCreate9/CreateDevice
Mars::Buffer::gobio subsystem in-progress — 0% 2026-09-07 .gob I/O; anchors the verify/ parser
serializable-types vs save structs verify mapped high 100% 2026-09-07 findings/objects/save-editor-structs.md (~130 structs, exact order); verifier: cross-check vs binary next
battle-load path subsystem mapped med 60% 2026-09-07 mitigation = affinity pin FUN_0089ee70; sim+load on main thread; see thread-contention row (parked)
class hierarchy + key vftables meta mapped high 100% 2026-09-07 findings/objects/ghidra-recon.md - RTTI Base_Class_Array read directly; vftables for 8 core classes
data-model (.gob data files) subsystem mapped high 100% 2026-09-07 findings/subsystems/data-model.md - tech/weapons/sections/races/AI all data-driven
string / config intel meta mapped high 100% 2026-09-07 findings/subsystems/strings-and-config.md
Mars brace-block parser subsystem verified high 100% 2026-09-07 verify/parsers/ (mars_data, flat_kv, manifest, effect_txt, verify.py): 1595/1595 files parse, 0 dangling cross-links; catalogs in verify/results/data-catalogs/
networking (SNM/FNM + GameSpy) subsystem backlog — 0% 2026-09-07 ~60 SNM strategy msgs, FNM file-xfer/host-migration; lockstep sim
battle-load: thread contention subsystem blocked med 60% 2026-09-07 PARKED (not on reimpl critical path). Profile: findings/subsystems/battle-load-profile.md. Combat not reached (no ships/range/encounters); audio thread inert w/o audio device; candidate = TryEnterCriticalSection->Sleep(1000) job poll @0x0071ea60 + 15.6ms timer. Resume recipe + tools in verify/harness/profiling/
UI screen & flow map meta mapped high 100% 2026-09-07 findings/subsystems/ui-screen-map.md - 36 screens; screens are C++ on Mars controls (NOT data); turn state machine recovered
Game::StrategyServer (sim block) object verified high 100% 2026-09-07 full member table (47 rows) confirmed vs real saves under strict parse incl. ID lists, GOWinPly, invasions, zdsc pairs, SvSctOb (present in all 3 saves)
stream primitive API subsystem mapped high 100% 2026-09-07 IStreamable vft: +0x18 string, +0x1c bool, +0x20 float, +0x24 int, +0x28 nested, +0x30 raw; FUN_00816490 = NetworkObject handle id
real save for verification verify verified high 100% 2026-09-07 6 saves, 3 distinct turn states in verify/results/saves/ (byte-deterministic per state). Game runs on VM140 via DXVK 3.1 + lavapipe; recipe findings/subsystems/running-the-game.md
save_reader.py verify verified high 100% 2026-09-07 --strict exit 0 on all 3 real saves; 0 resyncs / 0 hint-failures; only raw = RNG blob (2503 B). 29 tests. SAVE_FORMAT.md confirmed
Ghidra type write-back meta verified high 100% 2026-09-07 structs saved in project (ServerSystem 87f, ServerPlayer 110f, StarFleet, StarShip, StrategyServer partial, 22 nested); 52 serializers + primitives + ~60 spine fns renamed; decompile shows field names
strategic turn internals (economy/research/colony/movement/diplomacy) subsystem mapped high 90% 2026-09-07 findings/subsystems/strategic-turn-internals.md: budget/RP/trade/bankruptcy formulas, research rolls (unlisted race=1.0, Zuul x2), colony growth, movement, RNG=MT19937; ~600 g_KEY labels in Ghidra
P2-M0 shim bootstrap phase2 verified high 100% 2026-09-07 sots-engine 5f5bc41: proxy binkw32.dll (66 exports identical), MinHook, asm-stub trace hook on Application::Initialize; menu reached; evidence verify/results/shim/. Initialize signature unverified -> asm stubs only
P2-M1 flat-KV config loader phase2 verified high 100% 2026-09-08 LIVE: GlobalConsts::LoadFile hooked; trace 19 calls/1088 regions (tracecmp 0); compare 19/19, 0 divergences; REPLACE loaded all 19 files and End-Turn autosaves hashed exactly to the oracle; offline replay 0. 3 extra parsers found (string/vec3/rect), pi/180 is a double. sots-engine 8b231c0, docs/M1.md; traces verify/traces/m1-*
P2-M2 manifest/id registry phase2 verified high 80% 2026-09-08 LIVE: trace 22 calls (tracecmp 0); weapons compare 1/1 0 divergences; REPLACE+oracle byte-identical with our weapon loader feeding the game. Proves 123 weapon ids == manifest, DELETED lines are comments, dict sorted by _stricmp on name, +0x14 layout fix correct. GAP: section dictionary is TRACE-ONLY - ours crashes the engine in compare mode (leads in docs/M2.md; hooking LoadSection is the next boundary)
P2-M3 Mars brace-block parser phase2 backlog — 0% 2026-09-07 Mars::Script pull tokenizer (Open 0x008cd7d0, ReadToken 0x008cd2f0, Next 0x008cd3e0, SkipBlock 0x008cd4b0); whitespace-only delimiting, quotes " ' ` no escapes, EOF ends, stray } ignored, LAST PAIR W/O TRAILING NEWLINE DROPPED; consumers = _stricmp if/else chains (WeaponDef::ParseScript 0x00599070, SectionDef::ParseScript 0x005744e0, MasterTechTree::ParseTech 0x0058b050). .effect = Mars::TextFileStream (Open 0x008cfb90)
P2-M4 gobio VFS read phase2 backlog — 0% 2026-09-07 choke point: bool __cdecl gobio::ReadFile(const char*, IBuffer**) 0x008d5140; FileSystemSet ctor 0x008d6d60 pushes NativeFileSystem(".") FIRST then sots.ini [Modules] Mount (fallback sots.gob, sots_local_en.gob); zip lookup case+slash-insensitive 0x008d4a50 -> matches mars/vfs NativeFirst
loader prototypes (Ghidra) meta verified high 100% 2026-09-07 findings/subsystems/loader-prototypes.md: 80 entries (79 verified) in ghidra/addresses.json; Initialize = bool(this, AppStartup*) RET 4 (M0 crash explained); 93 fns renamed + 9 structs in Ghidra
compare harness verify mapped high 100% 2026-09-07 verify/harness/compare/: TRACE_FORMAT.md, tracecmp.py, replay, oracle bridge
engine: mars/parse engine verified high 100% 2026-09-07 sots-engine: brace-block + .effect readers; oracle 1531/1531; cross-compiles i686; wired into host+shim builds
engine: mars/text engine verified high 100% 2026-09-07 flat-kv, id-manifest, csv; oracle 64/64 (Strings.csv 5722 rows); ctest green
engine: game/sim formulas engine verified high 100% 2026-09-08 sim-pin merged: all 5 low-confidence formulas pinned (3.3 on protection limit, old-state bankruptcy decisions, hazard curve, money tail, pop bonus); tests 356->466; + game/effects (196 TechIds, 44 typed effects, 254 checks)
engine: mars/stream + rng engine verified high 100% 2026-09-07 merging: 100% exact dump agreement on 3 saves; typed shapes round-trip byte-identical whole file; RNG = seed(RSeed)+2 twists confirmed; 4 tag-name fixes for SAVE_FORMAT
engine: game/data catalogs engine verified high 100% 2026-09-07 merged: WeaponDef/ShipSectionDef/TurretTable/IdRegistry/TechTree/StringTable + cross_check; oracle 229,042 values 0 diffs; crosslink set reproduced exactly; 34 malformed shipped tokens pinned
engine: mars/vfs (gob) engine verified high 100% 2026-09-07 merged: ZIP reader + native override; 8352+2035 entries = unzip -l; all 10268 files CRC-clean; byte-equal spot checks; ctest 11/11
determinism oracle verify verified high 100% 2026-09-07 BYTE-IDENTICAL across 5 runs incl. cross-process: (Autosave).sav 978041ac…, (Autosave EndTurn).sav bb4fd9ac…; gzip MTIME=0; only loaded-post-turn re-save differs (Player.Status 4->0, Summary.Checksum). findings/subsystems/determinism-oracle.md
engine: shim trace/compare emitter engine verified high 100% 2026-09-07 merged (sots-engine 9e110b4): emitter byte-exact vs mkfixture, tracer, snapshot/diff, Hook; ctest 18/18; tracecmp exits 0/1/2 as specified; shim links
engine parity: first-wins keys + tokenizer rules engine verified high 100% 2026-09-07 merged: Mars::Script tokenizer rules, first-wins keys, trailing-pair drop in mars/parse+mars/text AND Python oracle; oracles 1531/1531, 64/64; only real-data effects: 2 dropped trailing pairs (engine uses defaults), systemnames.txt nesting
save-format tag corrections verify verified high 100% 2026-09-07 byte-confirmed at offsets (otnF x62, nextid, FAIDes/DHide/DWep/DName x43, ords, wpts, paths); reader A()-matches them; 36 tests; strict 3/3, infos 259->197; SAVE_FORMAT §10 changelog
tech effects (code-defined) subsystem mapped high 90% 2026-09-07 findings/subsystems/tech-effects.md: g_TechIdNames 196 @0x009ff9e4 (TechId=10000+i), effects in ServerPlayer::OnTechResearched 0x00891790; SpeciesDef table 0x00b10a00; 36 strategic / ~45 gates / ~115 none. Feeds game/sim + game/data
strategic formula gaps subsystem verified high 100% 2026-09-07 findings/subsystems/formula-gaps.md: all 8 answered with code (bankruptcy 3.3 on BnkPr, linear hazard, money tail, pbon, slider, [6] net, no speed clamp, decay hits current)
engine: game/design engine verified high 100% 2026-09-07 merged; see ShipDesignDef row
P2-B1 ComputeBudget (behavioral) phase2 verified med 75% 2026-09-08 LIVE + GREEN on declared regions (4,437 compares, 0 divergences; replace-mode oracle byte-identical). Corrections: out-param int[22]; researchMoneyKept gated on a research target. QUALIFIED BY THE HARNESS AUDIT: replace mode runs the ORIGINAL A SECOND TIME to harvest slots -> a real per-turn double effect (ComputeOutput repairs ships in orbit) that no region reaches - UNRESOLVED; the over-budget int at Budget+0x64 was captured only as an argument and args are never compared. Golden trace needs recapture with guards. Coverage gaps: 8 slots always 0 (expenses/aid/debt) . RECAPTURED WITH GUARDS 2026-09-08 (lane R): 4284 compared, 0 diverged, exit 0; budget_object guard 0 undeclared writes, so Budget+0x64 never took a different value (weaker than 'never written'). COVERAGE IS NARROWER THAN THE NUMBER: only 20 distinct (player, output) states in 4284 calls (4278 are the UI polling one player; the turn pass is ~8 calls), and 13 of the 22 slots are 0 on EVERY call - including 5 of the 6 declared input-boundary slots, which therefore prove nothing twice over. 8 modelled slots ever carry a value
P2-B2 OnTechResearched (behavioral) phase2 verified high 80% 2026-09-08 LIVE: 3 completions compared, 0 divergences (incl. one tech absent from the effects table = tail-only, the case an early return would have broken). float32 CONFIRMED ON THE GAME bit-for-bit (con_mod 1.0->0.899999976 = (float)(x+(double)0.1f)). Found B3's rolling effect: ServerPlayer::RollResearchEvent draws one NextFloat at the top of the callback - modelled + RNG region declared, but the branch never fired here so NOT behaviourally proven. KNOWN GAP: ours posts no events and the player event list is still undeclared, so the clean compare bounds the economy fields only and the replace/oracle pass was deliberately run on a no-completion turn (weak check) . RECAPTURED WITH GUARDS 2026-09-08 (lane R): 2 calls, 0 divergences; the player guard reports player+0x2b0 (EvNxID) on BOTH calls, so 'ours posts no events' is now measured, not assumed. RollResearchEvent branch FIRED and matched (see its row). Also caught an undeclared vector<ObservedTech> append at player+0x274. Reachable only after 5 End Turns from ref-turn2
P2-B3 ProcessResearch (behavioral, RNG) phase2 mapped high 85% 2026-09-08 LIVE, PARTIAL PASS: 15 calls compared, 13 zero-divergence; RNG post-state matched 14/15 incl. every roll (validates MT19937 + draw mapping + odds together). 2 divergences are the declared SetResearched boundary. ORACLE FAILS by exactly one item across 40,300: an unposted EVENT_RESEARCH_OVERBUDGET - compare was blind because the event list was never a declared region. fpu_cw=0x127f => 53-bit double, x87 question SETTLED. No Zuul in the save: double roll still disassembly-only . RECAPTURED WITH GUARDS 2026-09-08 (lane R): the oracle gap is now a COMPARE DIVERGENCE - side.events.after.v.next_id orig=4 ours=3 on call 0, its only divergent field, with node[144] progress 2879->5768 and flag 1->2 both reproduced and the single RNG draw identical. 15 calls over 5 turns: 3 diverged, RNG 15/15 (better than the original 14/15 - no tech-effect draw in this session). Guards on the two completion calls map SetResearched: ConMod[0..2]/OutMod/PopMod, ResTNm, TechTree+0x20 order counter, and the undeclared otch vector
RNG signatures (Ghidra) meta verified high 100% 2026-09-08 Seed/Twist/NextFloat/NextInt verified; draw = y/(2^32-1); NextInt [0,n] inclusive; lazy twist; left@+0x9c4. RUNTIME CONFIRMED: fpu_cw=0x127f (53-bit double, round-nearest) - our next_float model is right, float_from_pc24 is an unused contingency
engine: game/effects engine verified high 100% 2026-09-08 merged: TechId enum (196 slots @10000+i), 44 ids with typed strategic effects, species flag bits, ApplyTechEffect; 254 checks
VM140 exclusivity (lab rule) meta verified high 100% 2026-09-08 one agent at a time. Holder: F-fpucw (M-movefleet released 2026-09-08 03:49 local; R-recapture before it). QUEUE: empty. VM left at the MAIN MENU, hooks=trace, build recap-7584bad-20260908T0615Z restored from C:\SOTS\shimdist-recap (that dist also carries shim.cfg.recap{trace,b3,b1,misc}). Lane M also left C:\SOTS\shimdist-mf + C:\SOTS\ui\mf{deploy,release}.ps1 in place - harmless, and a working template for the next lane. Windows Update DISABLED/paused on the VM. Non-holders build /srv/re-lab/build/sots-engine-, stage dist-, deploy C:\SOTS\shimdist-. GOTCHA (lane R): after schtasks /Run /TN SOTS the main menu can take >60 s - SCREENSHOT AND VERIFY before clicking, or the click path lands in Credits. GOTCHA (lane M): drive the load dialog ONE rui.ps1 CALL PER CLICK with a screenshot between - a single chained cmd.txt loses sync and silently ends up somewhere else. And the Load Game dialog does NOT pre-select Single Player on a fresh launch: the documented path really is Load Game (512,536) -> Single Player (512,290) -> OK (551,523) -> row -> OK (682,624) -> Launch (511,663). ref-turn2 row is at (400,436)
Zuul double-roll (behavioural) verify backlog — 0% 2026-09-08 CONFIRMED NEEDED: ref-turn2 has only species 0 and 2, so the double roll is verified by disassembly + host tests only. Needs one compare from a species-5 save; the check is just that left drops by 2 not 1
budget tail coverage (expenses/aid/debt) verify backlog — 0% 2026-09-08 8 ComputeBudget slots were always 0 in ref-turn2 (no sliders, no aid, no debt, no handicap). Need a save with expense sliders, a debtor and a research-aid treaty to exercise ExpenseTotal + the aid/bonus tail . CONFIRMED AND WORSE 2026-09-08 (lane R, 4284 calls): 13 of 22 slots are 0 on every call - tradeIncome, shipCarriedPop, secondaryManager, bonusIncome, systemIncomeNeg, debtInterest, construction, expenses, researchMoneyGiven, savingsGiven, tra, researchPointsGiven, trp
hook GetDifficultyMods meta backlog — 0% 2026-09-08 B1 derived the two difficulty rows from trace values (AI maintenance divisor 3, research x1.5) instead of snapshotting them; hook it properly so they stop being constants
section-loader compare crash verify backlog — 0% 2026-09-08 SectionDictionary compare crashes the engine while the identical weapon path succeeds -> fault is in re-running LoadSection, not the manifest reader. Next boundary: hook LoadSection itself. docs/M2.md has 3 ranked leads
P2-B4 colony + movement (behavioral) phase2 mapped med 70% 2026-09-08 LIVE: 36 calls compared, 0 divergences, tracecmp exit 0. Scout's headline: RNG left-delta 0 and mt hash identical on ALL 28 systems (only ProcessRebellion draws; none fired) - fpu_cw 0x127f confirmed. One real fleet move reproduced bit-for-bit; PlanFleetMovement's schedule matched. 3 prototypes + 6 helpers VERIFIED and written back to Ghidra; 22 formula corrections. THREE hook bugs found by reading the trace, not the verdict (stale args from describe_args-before-regions; StrategyServer has TWO bases 4 bytes apart; off_Fleets was a Ghidra-base number used as raw) - each would have given a clean compare that checked nothing. COVERAGE IS THIN: only 3 owned systems, 1 moving fleet, gate traffic all-zero; bats2, plague, rebellion, slaves, terraform, jumps, arrivals untested. No replace mode (input boundary). VM released: main menu, hooks=trace, build b4-fix2-20260908T0615Z . QUALIFIED 2026-09-08 by lane R: with 45 MoveFleet calls over 5 turns instead of 7 over 1, 8 of the 15 moving calls diverge by 1 ULP of position. B4's clean verdict was a ONE-SAMPLE verdict - fleet 34 (its only mover) still matches bit-for-bit; the bug appears once other fleets move. ProcessTurn recaptured at 140 calls / 0 divergences, but only ntdev (15x) and rcex (7x) ever moved: everything else was byte-identical on all 140, so the verdict bounds two counters. Guard found the AI home system's fleet vector growing every turn (the build queue emitting a ship)
harness gap: undeclared side-effect lists verify verified high 100% 2026-09-08 FIXED STRUCTURALLY (engine 3f0721f+): compile-time-required Coverage on every descriptor (a hook without one does not compile); Guard regions that catch AND localise undeclared writes (names player+0x2b0, not 'the hash moved'); replace mode now emits records; tracecmp prints coverage on every report + --strict-coverage. A hook claiming 'complete' while a guard caught an undeclared write now counts as a DIVERGENCE. Audit found 23 undeclared side effects: docs/harness-audit.md
RollResearchEvent draw (behavioural) verify verified high 100% 2026-09-08 CLOSED by lane R. On turn 6 (IND_TRKSTL, tech 10094) research_roll_pending was true going in; the original drew exactly one word (rng left 375->374, next_index 249->250) and cleared the flag, and ours reproduced both bit-for-bit on the scratch generator. 0 divergences on that call. Needs 5 End Turns from ref-turn2 to reach - the reference turn has no completion at all
golden-trace recapture (post-guards) verify verified high 100% 2026-09-08 DONE on the live game, build recap-7584bad-20260908T0615Z (NO source change needed - the audit's machinery did all of it). B3 ProcessResearch: the defect is VISIBLE - side.events.after.v.next_id orig=4 ours=3, one divergent call of 3 on the reference turn and its ONLY divergent field; bit-for-bit the EvNxID 4->3 that previously needed a 609 KB save diff. Over 5 turns 15 calls / 3 diverged, RNG matched 15/15, and the two completion calls miss TWO event ids each. B1 ComputeBudget: verdict held - 4284 compared, 0 diverged, exit 0, budget_object guard caught 0 undeclared writes (Budget+0x64 never changed value). MoveFleet: 8 of 45 diverge by 1 ULP of position (new; see its own row). First guarded captures for OnTechResearched (2 calls), ServerSystem::ProcessTurn (140 calls) and MoveFleet (45). Guards mapped SetResearched live (ConMod[0..2], OutMod, PopMod, ResTNm, TechTree+0x20 order counter) and found an UNDECLARED vector<ObservedTech> otch append at player+0x274. Oracle held on every run's first End Turn. Report findings/subsystems/golden-trace-recapture.md; engine docs/R-recapture.md; traces verify/traces/recap-*, reports verify/results/compare/recap-*. sots-engine branch wip/recapture e50d5e5 (merged with main 82ef52f; ctest 32/32, clean-room OK)
MoveFleet position rounding (1 ULP) verify verified high 100% 2026-09-08 CLOSED by lane M. Mechanism read off the instruction stream, not fitted: the engine's Mars_Vec3_Normalize (0x00422520, 123 callers) narrows to float32 FOUR times - sumsq = f32(x*x+y*y+z*z) (products/adds stay in 53-bit regs, only the SUM is stored), len = f32(sqrt(sumsq)), inv = f32(1.0/len) a RECIPROCAL that is MULTIPLIED through rather than three divides, and dir.c = f32(delta.c*inv); and MoveFleet stores each dest.c - pos.c BACK TO A FLOAT32 SLOT before calling it, and takes the leg distance from that same call's return value. ours did all of it in double. The position tail (f32(pos + f32(dir*move))) was already right, which is exactly why the error was a constant ABSOLUTE ~1.2e-7. Confirmed OFFLINE first (an arrival copies the destination verbatim, so calls 115/155 hand you fleet 34's and fleet 50's exact float32 destinations = 8 fully determined legs; the 5-narrowing model reproduces the ORIGINAL bit-for-bit on all 8, the old double model reproduces ours on the 3 divergent ones), then LIVE: control run 8/45 diverged exit 1, fixed run 0/45 diverged exit 0, with identical args, identical pos.before and identical ORIGINAL pos.after on all 45 calls. Report findings/subsystems/movefleet-position-rounding.md, engine docs/M-movefleet.md, branch wip/movefleet 2aa8cba
undeclared ObservedTech append verify backlog — 0% 2026-09-08 NEW (lane R). A tech completion grows vector<ObservedTech> otch at ServerPlayer+0x274 (all three vector words move = a realloc). Seen as an undeclared write by BOTH the ProcessResearch player guard and the OnTechResearched player guard. It is serialized ServerPlayer state and it is in NO coverage note anywhere - a third list append in the same neighbourhood as the event list. B3's replace oracle never saw it because turn 1 of ref-turn2 has no completion
unnamed offsets from guard hits verify backlog — 0% 2026-09-08 NEW (lane R). Three spans the guards report every run and no addresses.json entry names: ServerSystem+0xd8 (1 B) and ServerSystem+0x238 (4 B) - written by the AI home system on every colony turn, alongside the fleet-vector growth; StarFleet+0xdc (1 B) - written on every moving MoveFleet call, just past Speed (FPsp2 @0xd8). Cheap wins for the contract
waypoint types 2-5 have no coverage verify backlog — 0% 2026-09-08 NEW (lane M, promoted from a coverage line to its own row because it is now the biggest gap in MoveFleet). Types 2 (node line), 3 (node route), 4 (gate teleport) and 5 (probabilistic jump) have NEVER fired in any capture, and the node-line step is WRONG BY CONSTRUCTION - sim::NodeLineStep and sim::BuildStutterSegments are written and host-tested but are NOT wired into the hook, which steps every waypoint type as speed x dt. ref-turn2 structurally cannot exercise them: lane M held the VM and tried. The only mover in that save is the AI, which travels straight runs; the player that would travel a node line has DE 00 CR 00 DN 00 at its home system (screenshot verify/results/shim/mf-human-home-no-ships.png), so Move/Manage Fleets are greyed out on every turn. Needs a ship built over several turns, or - much cheaper - a PURPOSE-BUILT SAVE with a fleet already in orbit next to a node line. Same save would unblock the gate-traffic and probabilistic-jump rows. Also owed on that path: sim::Distance is still plain double, and Mars_Vec3_Length (0x004224b0) says every vector length in the engine is float32-narrowed twice, so the stutter geometry is probably 1 ULP out the same way the position update was - deliberately left alone by lane M because there is no behavioural evidence to correct it against
ref-turn2 has no tech completion meta verified high 100% 2026-09-08 TRAP for anyone writing a workload (lane R). The documented one-End-Turn recipe produces zero OnTechResearched calls - an empty log that still passes. It takes 5 End Turns (to turn 7) to reach a completion. Also: only the FIRST End Turn is reproducible - it hashed to the oracle on all four runs and its research calls reproduce docs/B3.md exactly, but from turn 4 the AI picks a different research target than B3 recorded while the point totals stay nearly identical. Treat anything past turn 1 as a run, not the run
B1 replace double-run verify backlog — 0% 2026-09-08 ComputeBudget replace mode runs the original a second time to harvest budget slots; ComputeOutput repairs ships in orbit as a side effect, so this is a real per-turn double effect on objects no region covers. Needs a design fix (harvest without re-running, or declare+revert)
ReVa MCP link drop (workaround) meta verified high 100% 2026-09-08 The ReVa MCP client link dropped mid-session while the CT111 server stayed healthy (systemd active, :8080 listening, valid key -> 200). tools/reva_call.py <tool> '<json>' calls the same server over plain HTTP (initialize -> notifications/initialized -> tools/call; replies are SSE with a leading id: line, initialize is plain JSON). Key is NEVER stored in the repo: $REVA_KEY, else ~/.claude.json, else ssh to the CT properties file. Use this whenever mcp__plugin_ReVa_ReVa__* is unavailable
event posting API subsystem mapped high 90% 2026-09-08 RECOVERED (lane E, findings/subsystems/events.md). Container: EventStorage embedded at ServerPlayer+0x29c (0x1c), EvNxID at +0x14 = player+0x2b0 — exactly the guard's byte run. Nested vector<TurnEvents{int EvTurn; vector<PlayerEvent>}>, record 0x74 B, tags EvEID EvDsc EvMsg EvImg EvLoc EvPos EvAct EvCID; layout confirmed field-by-field against turn3-state.sav, which CONTAINS the overbudget record. Entry point int __thiscall EventStorage::PostEvent(this, string BYVAL, string BYVAL, obj*, Vector3*, turn, const char* img, int act) 0x008862b0 RET 0x4c — 161 call sites in 113 functions, the whole sim's event API. B3 defect fully explained: 0x00587b97, in the completion-roll-FAILED branch under !wasDone && nowDone && owner. 3 note corrections (EvPos is FLT_MAX not inf; the save array is turn-bucketed not flat; TECHS_UNLOCKED has no parent clause). 56 entries in addresses.json; 11 prototypes + 13 labels + 12 comments + 2 structs written back to Ghidra. Engine: sots-engine branch wip/events a7348be, src/game/events + 112 checks, ctest 32/32. NOT YET WIRED INTO A HOOK — see docs/E-events.md for the proposed region/Coverage change
state-checksum replay harness verify verified high 90% 2026-09-08 Lane C: verify/state-checksum/ (tool, 38 tests, STATE_CHECKSUM.md, evidence in verify/results/state-checksum/). Whole-state digest tree; coverage is PROVED by byte-for-byte re-serialisation, not declared - the answer to empty-region-set green verdicts. Localises: the known load->re-save delta reports as exactly 5 named leaves (/Sim/players/Player[496 "Singularity"]/Status: 4 -> 0, /Summary/Checksum), and one real End Turn as 108 attributed diffs. All 10 saves STABLE + COVERED. Float policy = exact bits by default, canonical for -0.0/NaN only, tolerance deliberately not a hashing mode (it lives in --ulps on the differ); corpus has 0 NaN/-0.0/subnormals so canonical is a no-op today. Chain record/verify validated on the real turn1-3 saves. REMAINING 10%: the VM-driven replay loop is designed (§5) but UNRUN - needs the VM holder. Open question named in §3.5 with the experiment that settles it (force fpu_cw 0x027f/0x127f/0x137f across End Turn, checksum the three autosaves)
MoveFleet position ULP divergence phase2 verified high 100% 2026-09-08 DONE (lane M). First arithmetic divergence caught by BEHAVIOURAL compare rather than static reading, and it is fixed by matching the original's precision sequence rather than by fitting numbers - see the MoveFleet position rounding (1 ULP) row for the mechanism. Live 8 -> 0 on the same 45 calls, control run included so the before/after is this lane's own measurement. COVERAGE IS UNCHANGED AND STILL THIN: 15 of 45 calls move and all 15 are the same straight-run waypoint type. Waypoint types 2-5 were ATTEMPTED and could NOT be reached - the only player that would travel a node line has DE 00 CR 00 DN 00 at its home system on this save, so its Move/Manage Fleets buttons are greyed out every turn and there is literally nothing to send along the node lines the map draws. Reaching them needs a ship BUILT over several turns, or (cheaper) a purpose-built save that starts with a fleet in orbit beside a node line. The node-line step is still wrong by construction: NodeLineStep/BuildStutterSegments exist and are unit-tested but are not wired into the hook
ObservedTech append (undeclared) verify backlog — 0% 2026-09-08 Lane R's guards caught a vector append at player+0x274 during SetResearched. It is SERIALIZED state and appears in NO coverage note anywhere - found only because guards localise rather than just flag a moved hash. Needs a declared region + a model in ours
fpu_cw sensitivity experiment verify backlog — 0% 2026-09-08 QUEUED FOR VM140 (lane M holds it). Lane C cannot tell whether any turn-pipeline value actually DEPENDS on x87 intermediate precision - every save on this host was made at fpu_cw=0x127f, so "the x64/SSE port must match bit-for-bit" is currently POLICY, not a measured requirement. Experiment: End Turn from ref-turn2.sav 3x with the shim forcing fpu_cw to 0x027f / 0x127f / 0x137f, then state_checksum the three autosaves. All equal => no double-rounding budget needed, closes STATE_CHECKSUM 3.5. Different => the diff IS the answer, naming every precision-sensitive field
Summary.Checksum algorithm objects blocked — 0% 2026-09-08 Lane C RULED OUT two candidates so nobody repeats them: NOT a byte sum over the inflated stream, NOT a sum over the int leaves. Each is consistent with the -16 re-save delta but leaves no constant residual across turns
event posting in ours phase2 in-progress — 0% 2026-09-08 Lane P: make ours actually post events so ProcessResearch's side.events.after.v.next_id 4->3 divergence closes. Converts harness-audit row 1 from known-defect to checked, and unbounds B2/B3 whose clean compares currently cover economy fields only
LAB RULE: no git add -A in sots-re while lanes run meta verified high 100% 2026-09-08 MY error, caught by lane M: an integrator git add -A in the SHARED sots-re clone swept a running lane's in-progress files into commit 9d385a7 mid-run (remainder landed in f5b37c2). Nothing was lost, but authorship and atomicity were. RULE: while any lane is live, the integrator stages sots-re by explicit PATH only (git add campaign/board.md campaign/DASHBOARD.md), never -A. Lanes own their own subtrees. sots-engine is unaffected - lanes work in per-lane worktrees there, which is exactly why that repo has not had this problem
MoveFleet waypoint types 2-5 verify backlog — 0% 2026-09-08 Still ZERO behavioural coverage after lane M. Not for lack of trying: the only mover in ref-turn2 is the AI (straight runs only), and the player that would travel a node line has DE/CR/DN all 00 at its home system, so Move/Manage Fleets are greyed out every turn - there is nothing to send along the node lines the map draws. Needs a ship built over several turns or a purpose-built save. The type-2 node-line step is still WRONG BY CONSTRUCTION (B4). Also: sim::Distance deliberately left in double (only stutter geometry uses it); Mars_Vec3_Length says it is probably 1 ULP out the same way, but there is zero behavioural evidence to correct it against - do not "fix" it blind