Commit graph

296 commits

Author SHA1 Message Date
lane P
0cd84690af lane P: SetResearched cascade read; 10 new addresses.json entries
Read TechTree::SetResearched (0x00581e10) end to end while wiring the research event
posts into ours (sots-engine wip/post-events). Two things it settles:

- SetResearched invokes the owner callback as vft+0x10(def, (flags>>2)&1), so bit 2 of
  flags IS OnTechResearched's "silent" argument. ProcessResearch passes flags = 2, so
  silent is FALSE and the completion event IS posted. Previously this was only
  inferable from lane R's observation that a completion call moved EvNxID by two.
- The unlock cascade in full: the node's child edges set child state 0->1 and
  child.costRP = min(child.costRP, edge.costRP); then a whole-tree sweep sets state 2
  and stamps turnAvailable from ModCount ONLY when it currently reads -1 (so it is
  sticky, and a node re-entering state 2 is not re-announced), and recurses into any
  zero-cost available node. Both loops test the node itself, not a parent -- there is
  no parent clause anywhere in the function, confirming lane E's correction.

Also records what is and is not known about vector<ObservedTech> at ServerPlayer+0x274:
the on-disk element shape is confirmed against turn3-state.sav (its string holds a tech
name), while sizeof(ObservedTech) and the append call site are still unpinned. The
cheapest route to the stride is now a measurement from the new observed_techs region,
not a search -- find-constant-uses does not index lea displacements.

New entries: ServerPlayer_off_ObservedTechs, TechNode_off_TurnAvailable /
TurnResearched / Order / Children, TechEdge_off_CostRP / ChildDef,
TechTree_off_OrderCounter, TechTree_SetResearched_flag_Force / _flag_Silent.
Generated header regenerated with tools/gen_addresses.py (386 -> 396 entries).
2026-09-08 04:16:59 -04:00
alex
b0ef139928 board: VM140 holder = lane F 2026-09-08 03:54:10 -04:00
alex
ada10f43d3 board: lane M verified (mechanism match, live 8->0); lab rule on path-scoped staging 2026-09-08 03:54:05 -04:00
alex
f5b37c2b34 lane M: MoveFleet position rounding closed; VM140 released; types 2-5 still uncovered
The mechanism, read off the instruction stream rather than fitted: Mars_Vec3_Normalize
(0x00422520, 123 callers) narrows to float32 four separate times, 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. Live 8/45 -> 0/45 with a control run of the unchanged
build, identical inputs and identical original outputs on all 45 calls.

Board: the two MoveFleet rows go verified; VM140 exclusivity back to FREE with two new
click-path gotchas; a new backlog row for waypoint types 2-5, which this lane attempted
and could not reach - ref-turn2 structurally cannot produce a node-line move because the
only player that would travel one has no ships.

(Most of this lane's files were swept into 9d385a7 by another lane's `git add -A` on the
shared repo; this commit carries what was left.)
2026-09-08 03:51:39 -04:00
alex
9d385a7683 board: lane C state-checksum landed; fpu_cw experiment queued; event-posting lane 2026-09-08 03:47:21 -04:00
alex
fdd0b72b7a state-checksum: whole-state diagnostic checksum harness (lane C)
The complement to the per-function compare harness. Instead of "did this
function's declared outputs match", it asks "is the entire simulation state
still identical" -- so no region-declaration mistake can hide from it.

Coverage is PROVED, not declared: the digest tree is re-serialised and compared
byte-for-byte against the inflated save on every run. When that reconstruction
reproduces the stream, the whole file is a function of the digest's inputs. A
run that cannot account for the file says so and exits non-zero. This is the
direct answer to B4's three hooks that printed "0 diverged" over an empty
region set.

It localises. The root is the fold of a per-subsystem / per-object tree with
named objects, so the known load->re-save delta reports as exactly five leaves
-- /Summary/Checksum and four /Sim/players/Player[...]/Status 4->0 -- naming the
two Singularity players by id where the raw byte diff could only say "1st of
two". One real End Turn reports as 108 fully attributed differences.

Float-parity policy is explicit and strict by default (STATE_CHECKSUM.md 3):
raw IEEE-754 bits; a `canonical` policy for signed zero and NaN payloads only;
and deliberately NO tolerant hashing mode, because quantisation moves the cliff
rather than removing it and destroys the roll-up. Tolerance lives in the differ
as --ulps, applied after localisation. Corpus census: 0 NaN, 0 -0.0, 0
subnormals across 4,474 float leaves, so the strict default costs nothing today
and a test fails the day that changes.

Validated on the real saves (verify/results/state-checksum/): 10 files, 4
distinct contents, all STABLE + COVERED; chain record/verify works on the real
turn1-3 saves. The VM-driven replay loop is designed (section 5) but UNRUN.

Section 3.5 names the one question the host side cannot settle -- whether the
turn pipeline depends on x87 intermediate precision -- and the experiment that
would: force fpu_cw to 0x027f / 0x127f / 0x137f across End Turn and checksum
the three autosaves.

Also recorded: Summary.Checksum is NOT a byte sum over the inflated stream nor
a sum over the int leaves (both ruled out), so nobody repeats those two.

38 tests; sots-engine untouched, clean_room_check.sh OK.
2026-09-08 03:46:34 -04:00
alex
1b893e57c3 dashboard refresh 2026-09-08 03:10:23 -04:00
alex
6f81b048e0 board: VM140 holder = lane M 2026-09-08 03:09:44 -04:00
alex
5b74b98778 board: claim VM140 for lane M; MoveFleet ULP + ObservedTech rows 2026-09-08 03:09:37 -04:00
alex
05095e93da lane R: golden-trace recapture with guards on the live game
Five hooks recaptured, build recap-7584bad-20260908T0615Z, no source change.

- ProcessResearch: the over-budget event is now a compare divergence
  (side.events.after.v.next_id orig=4 ours=3) instead of a 609 KB save diff.
  15 calls over 5 turns, 3 diverged, RNG matched 15/15.
- ComputeBudget: 4284 compared, 0 diverged, guard quiet - but only 20 distinct
  states and 13 of 22 slots always zero.
- MoveFleet: 8 of 45 calls diverge by 1 ULP of position. B4's clean verdict was
  a one-sample verdict.
- First guarded captures for OnTechResearched (RollResearchEvent draw fired and
  matched), the colony turn and MoveFleet.
- Guards mapped SetResearched live and found an undeclared ObservedTech append.

VM140 released at the main menu, hooks=trace.
2026-09-08 03:06:43 -04:00
alex
d738b6b4bb board: lane C state-checksum harness; dashboard refresh 2026-09-08 02:52:05 -04:00
alex
bd9b8f2e10 events: regenerate header (380 entries) 2026-09-08 02:50:38 -04:00
alex
e0c3e648d3 events: 161 call sites are spread over 113 functions, not 110 2026-09-08 02:47:42 -04:00
alex
0dff4941bd events: recover the player event-posting API (lane E)
Closes B3's oracle gap and B2's known gap. Both milestones write into the
owner's event list; nothing modelled it, so their clean compares bounded the
economy fields only.

Container: EventStorage embedded at ServerPlayer+0x29c (0x1c bytes), verified by
ServerPlayer::GetEventStorage 0x0080db00 whose whole body is 'lea eax,[ecx+0x29c];
ret'. EvNxID at +0x14 == player+0x2b0, exactly the byte run the harness guard
reports. The list is a vector<TurnEvents{int EvTurn; vector<PlayerEvent>}> --
bucketed by turn, not flat, which the save-editor struct note had wrong.

Entry point: int __thiscall EventStorage::PostEvent(this, std::string BY VALUE,
std::string BY VALUE, void* obj, Vector3* pos, int turn, const char* img,
int act), 0x008862b0, RET 0x4c. 161 call sites in 110 functions: this is the
whole simulation's event API, not a research helper. Dedup is per turn bucket on
message/image/location/position/action but NOT summary; act 0 with no subject and
no position is stored as 2; EvNxID starts at 0 and is promoted to 1 on first post;
PruneOldTurns drops buckets older than turn-50 with an off-by-one that always
leaves one stale bucket behind.

Record: 0x74 bytes, EvEID(+4) EvDsc(+8) EvMsg(+0x24) EvLoc(+0x40) EvPos(+0x44)
EvImg(+0x50) EvAct(+0x6c) EvCID(+0x70) -- confirmed field by field against
turn3-state.sav, which contains the EVENT_RESEARCH_OVERBUDGET record itself.

B3's defect is fully explained: 0x00587b97, reached only from the
completion-roll-FAILED branch, under !wasDone && nowDone && owner.

Three note corrections: EvPos defaults to FLT_MAX, not infinity (writing +inf
changes the save bytes); the save array is turn-bucketed, not flat;
EVENT_TECHS_UNLOCKED has no 'parent researched' clause.

56 entries added to ghidra/addresses.json (header regenerated); 11 prototypes,
13 labels, 12 comments and 2 structs written back to the Ghidra project.
2026-09-08 02:47:11 -04:00
alex
84d5609af8 dashboard: 50/65 mapped, 33 verified after B4 integration 2026-09-08 02:13:24 -04:00
alex
3b5eca29a2 reva_call.py: HTTP fallback for Ghidra when the MCP link drops; claim VM140 for recapture lane 2026-09-08 02:12:16 -04:00
alex
619edf97f4 regenerate header 2026-09-08 02:07:28 -04:00
alex
ff67ec0d9a b4 live artifacts; two-base StrategyServer hazard in the contract 2026-09-08 02:07:28 -04:00
alex
b878c4c48f harness audit merged; qualify B1/B4 claims with the blind spots it found 2026-09-08 01:30:33 -04:00
alex
cdada28d78 harness: coverage reporting + --strict-coverage in tracecmp 2026-09-08 01:28:36 -04:00
alex
84a0b7ceae B2 verified live; record the RollResearchEvent draw as behaviourally unproven 2026-09-08 01:19:47 -04:00
alex
ee43e96404 regenerate address header with b2 offsets 2026-09-08 01:19:05 -04:00
alex
5b6f812e31 b2 live artifacts; click_helper shot verb 2026-09-08 01:18:39 -04:00
alex
2d1a097b07 board: B4 code-complete with 22 corrections; harness audit lane opened 2026-09-08 00:58:59 -04:00
alex
4d535028ed b4 static findings: 22 formula corrections, 3 verified signatures, contract -> 324 entries 2026-09-08 00:57:55 -04:00
alex
535d1c3b58 B3 live partial pass; record the undeclared-side-effect-list harness gap 2026-09-08 00:30:32 -04:00
alex
ef3858c2ca regenerate address header 2026-09-08 00:29:44 -04:00
alex
8a6c0e8404 b3 live: fpu_cw settles x87 (53-bit); correct Q8 - research target is state 3 so it never decays 2026-09-08 00:29:44 -04:00
alex
83107f91f0 board: B2 code-complete with 10 corrections; B4 colony/movement lane opened 2026-09-08 00:02:10 -04:00
alex
db9b561964 b2 static findings: tech effects corrections, full g_TechIdNames dump; contract 176->211 2026-09-08 00:01:04 -04:00
alex
ead46e2608 M2 verified live (weapons); section compare crash recorded as a gap 2026-09-07 23:52:51 -04:00
alex
906858f60b B1 verified on the live game; record budget-tail coverage gap and the difficulty-mods shortcut 2026-09-07 23:26:54 -04:00
alex
3a3e167242 b1 corrections: budget out-param is int[22], researchMoneyKept gated on a research target 2026-09-07 23:24:58 -04:00
alex
1e7428d5aa board: B2 offline lane; VM queue M2/B3/B2 2026-09-07 23:15:46 -04:00
alex
6600382e12 b3 static findings: rng draw mapping, NextInt inclusive, float32 odds; address contract +17 2026-09-07 23:14:51 -04:00
alex
73f5f1e2ad board: B3 offline lane, VM queue M2 then B3 2026-09-07 22:44:02 -04:00
alex
f146a7616a m2 code merged (VM window pending); record the 3-word vector struct hazard 2026-09-07 22:43:05 -04:00
alex
01c3217b5c lab rule: VM140 shim deploys are exclusive; record the holder 2026-09-07 22:36:11 -04:00
alex
23b8eda585 board+dashboard: sim formulas pinned, game/effects merged, B1 in progress 2026-09-07 22:34:17 -04:00
alex
fa47bcdd6f correct the rng float-parity note: float10 is the x86 return ABI, not evidence of extended-precision math 2026-09-07 22:29:34 -04:00
alex
cea76e2771 rng: verify Seed/Twist/NextFloat signatures; lazy twist confirmed; flag x87 float-parity risk 2026-09-07 22:28:56 -04:00
alex
87a39b6731 plan the behavioral slice: B1 ComputeBudget, B2 OnTechResearched, B3 ProcessResearch (RNG); gate on RNG signatures 2026-09-07 22:24:44 -04:00
alex
8116f9e0c8 P2-M1 verified on the live game: golden trace, 0-divergence compare, replace passes the End-Turn oracle 2026-09-07 22:18:22 -04:00
alex
9e74691609 dashboard refresh (game/design merged, main green) 2026-09-07 22:15:45 -04:00
alex
e76e39ac03 board+dashboard: game/design merged 2026-09-07 22:11:29 -04:00
alex
602f108418 backlog: pin sim formulas + tech effects 2026-09-07 22:06:04 -04:00
alex
de7a2bef04 tech effects (196-entry TechId table, OnTechResearched), 8 formula gaps answered, std::string settled 2026-09-07 22:05:49 -04:00
alex
b24f13c613 addresses: GlobalConst/map layouts + float-scale global (M1 recon) 2026-09-07 22:01:49 -04:00
alex
8cdf3cd81d board+dashboard: engine parity merged 2026-09-07 22:01:26 -04:00
alex
31153cd278 parsers: engine parity (first-wins, Mars::Script tokenizer rules, trailing-pair drop); untrack pyc 2026-09-07 18:10:17 -04:00