board: lane ID - one allocator partitioned by node nibble; techId is the sorted index; 282 named

This commit is contained in:
alex 2026-09-08 20:28:15 -04:00
parent c60ee36a0e
commit 1bae6f1bfe

View file

@ -380,3 +380,9 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`).
| two type corrections, and the coverage figures were OPTIMISTIC too | verify | verified | high | 100% | 2026-09-08 | (1) `Game::CombatReport`: `auto`/`cdst` are **bools** and `dur`/`cdt`/`cdi` are **floats** - all five had been ints. Four are 0/1 everywhere so the bytes never moved, but **`cdt` was being read as 1070805848 for what is 1.598**. (2) `Game::CombatWeaponReport`'s damage quartet is flat with float dami/damt; the old shape reached them through an `obj_flex` nested `dams` frame **the binary never writes** - which made CoverageArchive charge **one phantom typed item per weapon report**. The four affected saves have 8/13/21/32 weapon reports and their totals moved by exactly 8/13/21/32, **so the pre-fix coverage figures were slightly OPTIMISTIC as well as too low** |
| FTPnts stays carried, and names its own workload | verify | backlog | — | 0% | 2026-09-08 | The one item the recovery itself marks `unresolved`, count 0 in every `Lay`. **It names the element class from the DECORATED HELPER NAME - exactly the SysMem/mts/nalat trap: the framing belongs to the helper, not the class.** Carried, with `Game::FieldTemplate::Point` deliberately left unbound. **The workload that settles it: a save with a stored fleet tactical formation** - set a fleet's combat layout in the tactical setup screen, then save. Everything else still carried is a never-filled container costing zero items on every save |
| LAB: CT111 direct SSH is publickey-denied | meta | verified | high | 100% | 2026-09-08 | Multiple lanes have now hit this and worked around it differently. **Direct `ssh 192.168.10.138` is denied; the working route is `ssh spicy` then `pct exec 111`.** Lane WS could not reach it at all and **installed g++-mingw-w64-i686 locally, cross-building against GCC 10-posix rather than CT111's toolchain** - so its "shim clean" was against a different compiler and the integrator re-ran the real one. Two facts it surfaced that are worth keeping: `TRmin` wanted a member named `min`, **which windows.h defines as a macro** (it is `mine` for that reason), and **the win32-threads variant of that compiler cannot build zip_archive.cpp at all** (`std::mutex` absent) - the posix variant is required. ReVa also stayed down (`CONNECTION_CLOSED`) the whole session; the server is `active` and CT111 is healthy at load ~15 from our own builds |
| THERE IS NO CLIENT-SIDE ALLOCATOR - one allocator, partitioned by node | objects | verified | high | 100% | 2026-09-08 | Lane ID, and it dissolves the question rather than answering it. **StrategyServer and StrategyClient are BOTH `Game::StrategySim`** (RTTI; StrategyServer carries vftables at offset 0 AND offset 4 - earned rule 1's "two bases 4 bytes apart", and the +4 one IS the StrategySim subobject). StrategySim owns an `IDMap` at **StrategySim+0x80**, so each sim allocates from **its own map on its own node index** using lane B5's one function. The entire protocol is a single branch in StrategySim::CreateDesign 0x008827e0: **`explicitId != 0 ? use it : AllocateOnLocalNode(this+0x80)`** - the client mints and puts the id in the command; the server runs THE SAME CODE and mints nothing. **`localNode = (PlyrIdx == -1) ? 0 : PlyrIdx + 1`** (four instructions at 0x007c8ecb): node 0 is the server's, player k gets node k+1. IDMap::Initialize caps nodes at **16 - that IS the nibble** - zeroes every counter and seeds only the local one. **NO COLLISION IS POSSIBLE**: the low nibble partitions the space; ~2,600 ids across 20 saves and 4 games, zero collisions, with nodes 1, 2 and 3 all occurring and each starting at counter 1 |
| save tags named: NMSz / NMLc / NMnx | objects | verified | high | 100% | 2026-09-08 | Falls straight out of IDMap::Initialize(numNodes, localNode, startId) 0x008b9ad0: **NMSz = node count, NMLc = local node, NMnx = that node's counter** - confirming lane B5's labelled hypothesis and adding the other two. A client is seeded from the SERVER's counter for its node via IDMap::GetNodeCounter. **Zero-residual id account of the reference turn** from the Sim block's master lists: ship 1760 (counter 110), fleet 1776 (111), fleet 34 (client counter 2), DesignIDs unchanged 43->43. TWO CORRECTIONS to turn-command-replay.md 4: 1712 was issued in turn 1->2, and **1776 is a fleet, not a design**; and **design 18 is already in turn2-state.sav**, so the canonical replay must mint exactly ONE id (fleet 34), not two |
| techId = the stricmp-SORTED index, closed offline | objects | verified | high | 95% | 2026-09-08 | No capture needed. Read out of MasterTechTree's constructor: it copies the parse-order list to a second vector, **std::sorts the copy with an inlined `_stricmp(a->name, b->name) < 0`**, then walks it writing `def->techId = i` at 0x0058ba29 - and the sorted vector doubles as the lower_bound name index, **which is WHY it is sorted**. That also explains lane RB's dead end: the parse-order table we held is THE OTHER VECTOR. **282 = XNC_TrnsHum2** - and **it was already in our notes, observed live by lane L4 in run R2 and never connected** (rule 18's corollary, paid for again). All four observed points hit exactly and it reproduces L4's six-member family as {282, 284, 286, 288, 290, 292}, so **Rung C-set's "we can name all k" CAN CLOSE**. `tools/techid_table.py` derives all 293 offline and **refuses to print unless the four observed points agree**. FLAGGED: the _stricmp half is disassembly-only - 48 of 293 ids differ from byte-wise order and no observed point discriminates |
| ID declined the third target, correctly | meta | verified | high | 100% | 2026-09-08 | It did NOT run the cbtrap set: that needs an End Turn on VM140, **which rewrites the three oracle autosaves**, and lane CB had already judged it the weaker check next to RB's zero-residual ModCount = 24. **Confirmatory value did not justify putting the reference bytes at risk.** It stays cheap for anyone who backs up SavedGames first, and the exact hashes are recorded in its finding. VM140 released with the oracle verified intact and the game never launched |
| ID's falsified prediction, with the probe named | verify | backlog | — | 0% | 2026-09-08 | Its prediction that client counters restart at 0 on load is **falsified by a corpus save**: lane CB's reloaded run produced fleet **34**, not 18. Either something restores the counter (six IDMap/InitGame functions read, no such write found) or **the client makes one earlier unsaved allocation per turn** - the second fits everything and implies the id collision has already happened harmlessly in CB's run. One hook on 0x008b8ae0 logging (map, node, id, return address) separates them |
| LAB TRAP: cmd.exe eats parentheses in save names | meta | verified | high | 100% | 2026-09-08 | `ssh ... certutil -hashfile "...(Autosave).sav"` fails with **"Check the spelling"**, which reads exactly like a missing file. Lane ID's first attempt **reported the three oracle saves as absent, and they were never absent** - a false alarm about the campaign's most important bytes |