From 164f14fa7f3ce897a4c95d877907c08b0017e366 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 8 Sep 2026 07:09:06 -0400 Subject: [PATCH] board: lane W wire sections closed, oracle fixes byte-neutral, CD negative result --- campaign/board.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/campaign/board.md b/campaign/board.md index 3758b7d..5070dfb 100644 --- a/campaign/board.md +++ b/campaign/board.md @@ -123,3 +123,9 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`). | Zuul completion (double roll + cascade) | verify | verified | high | 100% | 2026-09-08 | Lane U took it: call 2, turn 7, species 5 - `left` 449->447 (DOUBLE ROLL) AND the cascade in the SAME call, next_id 10->12, observed_techs 396->440. Independent instance: the Zuul tree unlocks only 132/136 from tech 144 where the Human tree also unlocks 142 | | RollResearchEvent draw - why it never fires | verify | mapped | high | 90% | 2026-09-08 | Lane U's honest limit: roll_draws was 0 on ALL 35 calls. The draw is modelled, its inputs are read pre-call and reported in every record, and region:rng compares clean - but THE BRANCH HAS NEVER BEEN SEEN TO FIRE. The reason is a real finding: ResearchRollPending is normally consumed by ServerPlayer::ProcessTurn BEFORE ProcessResearch, because that site fires when the progress ratio crosses its threshold - exactly the turns approaching completion. In the Zuul run it is true for turns 8-12 and flips FALSE on turn 13, the turn before completion on turn 14. So lane V's call-9 draw was the RARE case and lane R's "15/15" the common one. Three sessions: 0 / 1 / 0. Closing it needs a purpose-built save | | VM: use QEMU screendump, not the click helper's shot | meta | verified | high | 100% | 2026-09-08 | Lane U: `qm monitor 140` screendump is more reliable than the click helper's `shot`. Also the >60 s startup got its FOURTH confirmation (menu at ~t+85 s) | +| wire sections closed (SvSctOb/DOpts/spies2) | engine | verified | high | 95% | 2026-09-08 | Lane W: named coverage 97.1 -> 98.0% (zuul 97.6 -> 98.4), conformance 56 shapes/657 items -> 74/769, STILL 0 MISMATCH, every new binding 0 wire-only 0 shape-only. Ratchet 95.0 -> 97.5. SvSctOb (147/156/156/126 -> 0): body is Game::SVSOSots writing two POLYMORPHIC lists keyed by the item before them (xscn->xsc, EncID->EncObj); NEITHER MAP IS ON THE WIRE - both came out of the binary: EncID from a 23-entry dword JUMP TABLE at 0x0052bf60 indexed by EncID-1 (factory 0x0052bf00, class names read off each ctor's vftable store), xscn from an exhaustive four-way _stricmp chain at 0x005a7050. The eight ids in our saves had been identified by tag-sequence match; the table AGREED on all eight and added four more. DOpts (94 -> 0) and spies2 (56 -> 0) are certain FROM THE HELPER'S OWN DECORATED TYPE - VectorHelper and VectorHelper - not inferred from bytes | +| spies2/SysMem/mts are HYPOTHESES not results | verify | backlog | — | 0% | 2026-09-08 | Lane W flagged as instructed: spies2's count is 0 in all 28 systems of all four saves, so the 56 items "closed" are 28 x (frame + count) and NO ELEMENT VALUE HAS EVER BEEN OBSERVED. Same for SysMem and mts. A layout you cannot exercise is a hypothesis - needs a workload | +| CD custom data: provable negative | objects | mapped | high | 80% | 2026-09-08 | Lane W's static read gave a NEGATIVE RESULT WORTH HAVING: the recovered 44-item Game::TurnCommands sequence CANNOT be aligned to the save's 35 items even as a SUBSEQUENCE. Item 4 is 8 bytes on disk, which for a 1-char tag can only be a BOOL where the recovery says i32; and the 27 trailing ints have only 22 i32 slots available after index 15. Confirms a save with issued orders is required (lane O). ALSO SPLIT INTO TWO PROBLEMS: TurnCommands_v5 (blocked on a workload) vs THREE AIAgent blocks (~236 items each = the BULK of the 744) which are Game::StrategyAIAgent::Streamable with NAMED tags, statically tractable, ~10 nested shapes - deliberately left for a following lane since it is AI cache state, not orders | +| SvSctOb side findings | objects | verified | high | 100% | 2026-09-08 | `indsys` = Game::SVSOIndependentSystems, whose Read AND Write are both the shared `ret 4` stub - its EMPTY FRAME IS CORRECT OUTPUT, not truncation. SVSOMonitor derives from SVSODerelict (its Write calls Derelict's first). SVSOSots::Read accepts NPCPlr/hastraps that Write NEVER EMITS - read-only back-compat, not a recovery hole. And THE RECOVERY IS WRONG about SVSOCrowDefenders::dsys - it is inside the ndsys loop, which no save can settle. EncIDs 7/8/14/21 and ScnObj have factory entries and recovered serializers but NO OCCURRENCE anywhere - deliberately carried as Nodes, not typed | +| four oracle fixes landed, byte-neutral | verify | verified | high | 100% | 2026-09-08 | Lane W fixed all four OPENLY with 12 new tests: 36 -> 48 tests passing, --strict exit 0 on all four saves, state_checksum coverage PROVED on all four with unchanged rebuilt byte counts. BYTE-NEUTRALITY PROVEN AT ITEM GRANULARITY: dumping every save before and after, the OFFSET SEQUENCES ARE IDENTICAL (38,933/39,843/40,300/35,771 offsets, no item boundary moved); the /CreateParams and /Sim/players digests DO change, correctly, because they hash typed values, and the value-byte deltas balance EXACTLY (odet x3 + p1 x4 = 292/295/295/238, to the byte). NUANCE: defects 3 and 4 were an ABSENCE in save_reader.py, not an error - ShipRecs and civr were both A(...,"any"), so the fix ADDED typed shapes rather than retyping a field, a bigger change than my brief implied. srbd turned out BEHAVIOURALLY CONFIRMED not inferred: it takes 0/1/3/4 across players and every non-zero count is followed by exactly srbd x 5 scalars (turn3 player 4: srbd==4, 20 items) - read as a field those trailing scalars have no explanation. `nv` is WEAKER: only ever 0 or 1 in these saves, so the multi-pair case is synthetic | +| save_reader silent-agreement failure mode | verify | verified | high | 100% | 2026-09-08 | Forced into the open by lane W's tests: save_reader.py's walker types "." items from its OWN kind catalog, not the schema passed in - so on the real saves the catalog and the old schema agreed with each other AND WERE BOTH WRONG. Its failure mode is SILENT AGREEMENT, not the framing desync the schema-driven engine would have suffered. Two independent-looking checks that share a hidden assumption are one check |