## tracecmp report: v-b3-t1-5.jsonl - build: eventlive-dd38117-20260908T0916Z started: 2026-09-08T09:20:00Z inline_max: 256 - calls: 15 compared: 15 diverged: 2 invalid records: 0 warnings: 0 - coverage: 15 guarded call(s), 10 undeclared write(s) in 2 call(s); 0 hook(s) unstated, 0 contradicted | hook | calls | modes | compared | diverged | errors | |---|---|---|---|---|---| | Game::TechTree::ProcessResearch | 15 | compare:15 | 15 | 2 | 0 | ### coverage | hook | verdict | compared regions | guards | undeclared writes | unmodelled | |---|---|---|---|---|---| | Game::TechTree::ProcessResearch | partial | events, node[0], node[105], node[106], node[107], node[108], +271 | player, tree_header | 10 in 2 call(s) | 6 | #### Game::TechTree::ProcessResearch — not checked by this run - (medium) posts EVENT_RESEARCH_OVERBUDGET on the owner's EventStorage: ours reproduces the decision and the id sequence, so region:events compares next_id, but the composed EvDsc/EvMsg text is not reproduced and no region can see it — text comes from the game's string table, which the engine must not carry; ours posts into its own EventStorage and writes only the counts into the scratch copy, so no live byte moves and replace mode posts nothing at all [region:events] - (medium) posts EVENT_TECHS_UNLOCKED once after the per-node loop, for the nodes SetResearched made available this turn — the set comes from the child-unlock cascade, which ours does not run; the pass driver takes the unlock list as an input and is given `no list` rather than an empty one, so a missing input cannot look like a modelled negative. Expect region:events to under-count next_id by exactly 1 on every call that completes a tech [region:events] - (high) appends to the owner's vector (ServerPlayer+0x274) on every tech completion — serialized ServerPlayer state that no coverage note in B2 or B3 mentioned until lane R's guard caught it. The element is now fully pinned (sizeof 44, {u16 turn_first, u16 turn_last, bool detected, string tech_name, int with}) and the append de-duplicates by tech name, but ours still does not append; the region reports the byte span, which must grow by exactly 44 per completion [region:observed_techs] - (high) TechTree::SetResearched on completion: the turn/order stamps, the child unlock cascade, the recursive research of zero-cost children, and the owner's OnTechResearched callback — its own milestone (B2); the callback writes live player state that compare mode must not touch, and it consumes one extra RNG word [guard:player, guard:tree_header] - (medium) bumps the tree's completion-order counter (TechTree+0x20) — part of SetResearched; the per-node `order` word is compared but the counter it comes from was not a region [guard:tree_header] - (low) writes a completion line to the game log — log text is not simulation state - guard hits in compare mode: player+0x10c:3, player+0x110:3, player+0x114:3, player+0x124:3, player+0x294:4, tree_header+0x20:1, player+0x196:1, player+0x3b4:1 ### Game::TechTree::ProcessResearch: first 2 of 2 divergent call(s) - call_id 3 (v-b3-t1-5.jsonl:5) side.events.after.v.next_id [exact] orig={"t":"i32","v":7} ours={"t":"i32","v":6} side.node[132].after.v.cost_rp [exact] orig={"t":"i32","v":10000} ours={"t":"i32","v":2147483647} side.node[132].after.v.state [exact] orig={"t":"i32","v":2} ours={"t":"i32","v":0} side.node[132].after.v.turn_available [exact] orig={"t":"i32","v":4} ours={"t":"i32","v":-1} side.node[136].after.v.cost_rp [exact] orig={"t":"i32","v":16000} ours={"t":"i32","v":2147483647} side.node[136].after.v.state [exact] orig={"t":"i32","v":2} ours={"t":"i32","v":0} side.node[136].after.v.turn_available [exact] orig={"t":"i32","v":4} ours={"t":"i32","v":-1} side.node[142].after.v.cost_rp [exact] orig={"t":"i32","v":8000} ours={"t":"i32","v":2147483647} … 5 more - call_id 9 (v-b3-t1-5.jsonl:11) side.events.after.v.next_id [exact] orig={"t":"i32","v":12} ours={"t":"i32","v":11} side.node[133].after.v.cost_rp [exact] orig={"t":"i32","v":8000} ours={"t":"i32","v":2147483647} side.node[133].after.v.state [exact] orig={"t":"i32","v":2} ours={"t":"i32","v":0} side.node[133].after.v.turn_available [exact] orig={"t":"i32","v":6} ours={"t":"i32","v":-1} side.node[142].after.v.order [exact] orig={"t":"i32","v":23} ours={"t":"i32","v":-1} side.node[142].after.v.turn_researched [exact] orig={"t":"i32","v":6} ours={"t":"i32","v":-1} side.observed_techs.after.v.bytes [exact] orig={"t":"i32","v":528} ours={"t":"i32","v":484} side.rng.after.v.left [exact] orig={"t":"i32","v":374} ours={"t":"i32","v":375} … 1 more