lane E2: T36 measured with the ship census wired in -- 29 closed / 7 regressed, and the two things it is still blocked on
standalone_report.py regenerated from sots-engine wip/turnrecord. The reference pair does not move by design: T36 does not commit by default, so 209 -> 204, closed 5 / regressed 0 and 108 -> 103, closed 5 / regressed 0 are unchanged. What moved in section 6 is the phase tally, 14/44 modelled and 8 committed -> 15/44 and 9, from the A2 and D2 merges. verified stays 0 on both tables. t36-turnrecord.md carries the measurement the default run cannot show: with --commit-blocked=T36 and a data root, the reference pair closes 29 leaves and regresses 7 (was 9). Two of the three census leaves close; the third is short by exactly one destroyer on both pairs, because no phase we run builds a ship. The census model itself reproduces 480/480 archived census leaves over 11 saves with 0 mismatches. T36 stays blocked: sav and inc on lane E1's budget, and one ship count on unmodelled construction. A field-granular commit knob is not implementable -- the archived record is one struct on the wire and has no hole to leave. Coverage: 32 of 480 census leaves are nonzero anywhere in the corpus; cls1 and cls2's platform count are unexercised, not verified.
This commit is contained in:
parent
3a44f9178b
commit
fbe3c7bd86
3 changed files with 186 additions and 42 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
# standalone vs the oracle
|
# standalone vs the oracle
|
||||||
|
|
||||||
generated 2026-09-08T15:35:00Z binary /home/alex/sots-engine-wt-yield/build-host/src/app/sots_turn
|
generated 2026-09-08T17:23:54Z binary /home/alex/sots-engine-wt-turnrecord/build-host/src/app/sots_turn
|
||||||
|
|
||||||
phases: 14/44 of the two turn drivers modelled, 8 committed (implemented 2, partial 6, blocked 6, stub 30)
|
phases: 15/44 of the two turn drivers modelled, 9 committed (implemented 3, partial 6, blocked 6, stub 29)
|
||||||
3/37 of the post-combat tail modelled
|
3/37 of the post-combat tail modelled
|
||||||
|
|
||||||
## turn1-state.sav -> turn2-state.sav (real End Turn)
|
## turn1-state.sav -> turn2-state.sav (real End Turn)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"schema": "sots-standalone-status/1",
|
"schema": "sots-standalone-status/1",
|
||||||
"generated": "2026-09-08T15:35:00Z",
|
"generated": "2026-09-08T17:23:54Z",
|
||||||
"binary": "/home/alex/sots-engine-wt-yield/build-host/src/app/sots_turn",
|
"binary": "/home/alex/sots-engine-wt-turnrecord/build-host/src/app/sots_turn",
|
||||||
"reference": {
|
"reference": {
|
||||||
"input": "turn1-state.sav",
|
"input": "turn1-state.sav",
|
||||||
"oracle": "turn2-state.sav",
|
"oracle": "turn2-state.sav",
|
||||||
|
|
@ -30,12 +30,12 @@
|
||||||
"phases": {
|
"phases": {
|
||||||
"total": 44,
|
"total": 44,
|
||||||
"verified": 0,
|
"verified": 0,
|
||||||
"implemented": 2,
|
"implemented": 3,
|
||||||
"partial": 6,
|
"partial": 6,
|
||||||
"blocked": 6,
|
"blocked": 6,
|
||||||
"stub": 30,
|
"stub": 29,
|
||||||
"modelled": 14,
|
"modelled": 15,
|
||||||
"committed": 8
|
"committed": 9
|
||||||
},
|
},
|
||||||
"tailPhases": {
|
"tailPhases": {
|
||||||
"total": 37,
|
"total": 37,
|
||||||
|
|
@ -62,16 +62,17 @@
|
||||||
" 591376 inflated bytes, 0 error(s), 0 warning(s)",
|
" 591376 inflated bytes, 0 error(s), 0 warning(s)",
|
||||||
" turn 1, frame 1, modCount 0, 8 player(s), 28 system(s), 6 fleet(s)",
|
" turn 1, frame 1, modCount 0, 8 player(s), 28 system(s), 6 fleet(s)",
|
||||||
"roundtrip (untouched): byte-identical (591376 bytes)",
|
"roundtrip (untouched): byte-identical (591376 bytes)",
|
||||||
|
"data: /tmp/claude-1000/-home-alex/ec8e34f8-af37-4ef2-a309-ed6a15293097/scratchpad/data -- 885 section(s) over 7 race(s), 46 load problem(s)",
|
||||||
"",
|
"",
|
||||||
"phases",
|
"phases",
|
||||||
" turn drivers (the milestone's denominator): 14 of 44 modelled, 8 committed",
|
" turn drivers (the milestone's denominator): 15 of 44 modelled, 9 committed",
|
||||||
" verified 0 implemented 2 partial 6 blocked 6 stub 30",
|
" verified 0 implemented 3 partial 6 blocked 6 stub 29",
|
||||||
" post-combat tail (written to the autosave, tracked separately): 3 of 37 modelled",
|
" post-combat tail (written to the autosave, tracked separately): 3 of 37 modelled",
|
||||||
" verified 0 implemented 1 partial 0 blocked 2 stub 34",
|
" verified 0 implemented 1 partial 0 blocked 2 stub 34",
|
||||||
"",
|
"",
|
||||||
"this run",
|
"this run",
|
||||||
" leaves written 7",
|
" leaves written 7",
|
||||||
" leaves NOT written by a blocked phase 64",
|
" leaves NOT written by a blocked phase 120",
|
||||||
" generator words consumed 16 (state loaded, left untouched)",
|
" generator words consumed 16 (state loaded, left untouched)",
|
||||||
" generator words NOT accounted (never netted off the above):",
|
" generator words NOT accounted (never netted off the above):",
|
||||||
" - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled",
|
" - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled",
|
||||||
|
|
@ -80,8 +81,8 @@
|
||||||
" ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)",
|
" ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)",
|
||||||
" ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's",
|
" ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's",
|
||||||
"",
|
"",
|
||||||
"wrote /tmp/tmp_cz5dsbf/post-turn1-state.sav (65145 bytes gzipped, 591376 inflated)",
|
"wrote /tmp/tmpbodkynxg/post-turn1-state.sav (65145 bytes gzipped, 591376 inflated)",
|
||||||
"metric -> /tmp/tmp_cz5dsbf/metric-turn1-state.sav.json"
|
"metric -> /tmp/tmpbodkynxg/metric-turn1-state.sav.json"
|
||||||
],
|
],
|
||||||
"coverage": {
|
"coverage": {
|
||||||
"input": true,
|
"input": true,
|
||||||
|
|
@ -89,9 +90,9 @@
|
||||||
"ours": true
|
"ours": true
|
||||||
},
|
},
|
||||||
"roots": {
|
"roots": {
|
||||||
"input": "ce36f6e5a2e41ae1a90d5b7fefda8f8f",
|
"input": "64b836b966299d9b72fc02244ed31e31",
|
||||||
"oracle": "b0e2448b83ad1da254d526f4f553ff8d",
|
"oracle": "4bed514f853332b9fa35b388c3aa5558",
|
||||||
"ours": "8836ea25910897ec7a9b7d69fcaf6c87"
|
"ours": "1acc372b1d410b966ab544dffbe43cb5"
|
||||||
},
|
},
|
||||||
"baselineDiverging": 209,
|
"baselineDiverging": 209,
|
||||||
"divergingAfterTurn": 204,
|
"divergingAfterTurn": 204,
|
||||||
|
|
@ -151,16 +152,16 @@
|
||||||
"standalone": {
|
"standalone": {
|
||||||
"schema": "sots-standalone-metric/1",
|
"schema": "sots-standalone-metric/1",
|
||||||
"input": "/home/alex/sots-re/verify/results/saves/turn1-state.sav",
|
"input": "/home/alex/sots-re/verify/results/saves/turn1-state.sav",
|
||||||
"output": "/tmp/tmp_cz5dsbf/post-turn1-state.sav",
|
"output": "/tmp/tmpbodkynxg/post-turn1-state.sav",
|
||||||
"spine": {
|
"spine": {
|
||||||
"total": 44,
|
"total": 44,
|
||||||
"verified": 0,
|
"verified": 0,
|
||||||
"implemented": 2,
|
"implemented": 3,
|
||||||
"partial": 6,
|
"partial": 6,
|
||||||
"blocked": 6,
|
"blocked": 6,
|
||||||
"stub": 30,
|
"stub": 29,
|
||||||
"modelled": 14,
|
"modelled": 15,
|
||||||
"committed": 8
|
"committed": 9
|
||||||
},
|
},
|
||||||
"tail": {
|
"tail": {
|
||||||
"total": 37,
|
"total": 37,
|
||||||
|
|
@ -174,7 +175,7 @@
|
||||||
},
|
},
|
||||||
"run": {
|
"run": {
|
||||||
"leafWrites": 7,
|
"leafWrites": 7,
|
||||||
"blockedLeafWrites": 64,
|
"blockedLeafWrites": 120,
|
||||||
"rngWords": 16,
|
"rngWords": 16,
|
||||||
"rngLoaded": true,
|
"rngLoaded": true,
|
||||||
"rngCommitted": false,
|
"rngCommitted": false,
|
||||||
|
|
@ -239,8 +240,8 @@
|
||||||
"driver": "StrategyServer::ProcessTurn",
|
"driver": "StrategyServer::ProcessTurn",
|
||||||
"id": "S04",
|
"id": "S04",
|
||||||
"name": "RebuildAllianceMasks",
|
"name": "RebuildAllianceMasks",
|
||||||
"status": "stub",
|
"status": "implemented",
|
||||||
"ran": 0,
|
"ran": 8,
|
||||||
"writes": 0,
|
"writes": 0,
|
||||||
"blockedWrites": 0,
|
"blockedWrites": 0,
|
||||||
"rng": 0
|
"rng": 0
|
||||||
|
|
@ -1002,7 +1003,7 @@
|
||||||
"status": "blocked",
|
"status": "blocked",
|
||||||
"ran": 8,
|
"ran": 8,
|
||||||
"writes": 0,
|
"writes": 0,
|
||||||
"blockedWrites": 48,
|
"blockedWrites": 104,
|
||||||
"rng": 0
|
"rng": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -1028,16 +1029,17 @@
|
||||||
" 603360 inflated bytes, 0 error(s), 0 warning(s)",
|
" 603360 inflated bytes, 0 error(s), 0 warning(s)",
|
||||||
" turn 2, frame 2, modCount 12, 8 player(s), 28 system(s), 7 fleet(s)",
|
" turn 2, frame 2, modCount 12, 8 player(s), 28 system(s), 7 fleet(s)",
|
||||||
"roundtrip (untouched): byte-identical (603360 bytes)",
|
"roundtrip (untouched): byte-identical (603360 bytes)",
|
||||||
|
"data: /tmp/claude-1000/-home-alex/ec8e34f8-af37-4ef2-a309-ed6a15293097/scratchpad/data -- 885 section(s) over 7 race(s), 46 load problem(s)",
|
||||||
"",
|
"",
|
||||||
"phases",
|
"phases",
|
||||||
" turn drivers (the milestone's denominator): 14 of 44 modelled, 8 committed",
|
" turn drivers (the milestone's denominator): 15 of 44 modelled, 9 committed",
|
||||||
" verified 0 implemented 2 partial 6 blocked 6 stub 30",
|
" verified 0 implemented 3 partial 6 blocked 6 stub 29",
|
||||||
" post-combat tail (written to the autosave, tracked separately): 3 of 37 modelled",
|
" post-combat tail (written to the autosave, tracked separately): 3 of 37 modelled",
|
||||||
" verified 0 implemented 1 partial 0 blocked 2 stub 34",
|
" verified 0 implemented 1 partial 0 blocked 2 stub 34",
|
||||||
"",
|
"",
|
||||||
"this run",
|
"this run",
|
||||||
" leaves written 7",
|
" leaves written 7",
|
||||||
" leaves NOT written by a blocked phase 58",
|
" leaves NOT written by a blocked phase 114",
|
||||||
" generator words consumed 16 (state loaded, left untouched)",
|
" generator words consumed 16 (state loaded, left untouched)",
|
||||||
" generator words NOT accounted (never netted off the above):",
|
" generator words NOT accounted (never netted off the above):",
|
||||||
" - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled",
|
" - encounter detection draws one unit value and one bounded integer per turn on every turn measured (2 words), with no derived rule behind the count -- its bound is the product of the contact and detector counts, so it is left unmodelled",
|
||||||
|
|
@ -1046,8 +1048,8 @@
|
||||||
" ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)",
|
" ! the generator advanced during this run but the save keeps its original state (--commit-rng to write it)",
|
||||||
" ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's",
|
" ! the modelled words are a LOWER BOUND on the turn's cost, so a committed generator is short by the unaccounted sites below and its drawn VALUES are not the game's",
|
||||||
"",
|
"",
|
||||||
"wrote /tmp/tmp_cz5dsbf/post-turn2-state.sav (66883 bytes gzipped, 603360 inflated)",
|
"wrote /tmp/tmpbodkynxg/post-turn2-state.sav (66883 bytes gzipped, 603360 inflated)",
|
||||||
"metric -> /tmp/tmp_cz5dsbf/metric-turn2-state.sav.json"
|
"metric -> /tmp/tmpbodkynxg/metric-turn2-state.sav.json"
|
||||||
],
|
],
|
||||||
"coverage": {
|
"coverage": {
|
||||||
"input": true,
|
"input": true,
|
||||||
|
|
@ -1055,9 +1057,9 @@
|
||||||
"ours": true
|
"ours": true
|
||||||
},
|
},
|
||||||
"roots": {
|
"roots": {
|
||||||
"input": "b0e2448b83ad1da254d526f4f553ff8d",
|
"input": "4bed514f853332b9fa35b388c3aa5558",
|
||||||
"oracle": "7ea50b486c2e9f9f1a8ec5b9646165a8",
|
"oracle": "e9c161e311f8ef8fad6f1aa1903dcf3f",
|
||||||
"ours": "6523aa25786814380a26f48c046da22b"
|
"ours": "22071ae1303f308a93b805e940b626b5"
|
||||||
},
|
},
|
||||||
"baselineDiverging": 108,
|
"baselineDiverging": 108,
|
||||||
"divergingAfterTurn": 103,
|
"divergingAfterTurn": 103,
|
||||||
|
|
@ -1117,16 +1119,16 @@
|
||||||
"standalone": {
|
"standalone": {
|
||||||
"schema": "sots-standalone-metric/1",
|
"schema": "sots-standalone-metric/1",
|
||||||
"input": "/home/alex/sots-re/verify/results/saves/turn2-state.sav",
|
"input": "/home/alex/sots-re/verify/results/saves/turn2-state.sav",
|
||||||
"output": "/tmp/tmp_cz5dsbf/post-turn2-state.sav",
|
"output": "/tmp/tmpbodkynxg/post-turn2-state.sav",
|
||||||
"spine": {
|
"spine": {
|
||||||
"total": 44,
|
"total": 44,
|
||||||
"verified": 0,
|
"verified": 0,
|
||||||
"implemented": 2,
|
"implemented": 3,
|
||||||
"partial": 6,
|
"partial": 6,
|
||||||
"blocked": 6,
|
"blocked": 6,
|
||||||
"stub": 30,
|
"stub": 29,
|
||||||
"modelled": 14,
|
"modelled": 15,
|
||||||
"committed": 8
|
"committed": 9
|
||||||
},
|
},
|
||||||
"tail": {
|
"tail": {
|
||||||
"total": 37,
|
"total": 37,
|
||||||
|
|
@ -1140,7 +1142,7 @@
|
||||||
},
|
},
|
||||||
"run": {
|
"run": {
|
||||||
"leafWrites": 7,
|
"leafWrites": 7,
|
||||||
"blockedLeafWrites": 58,
|
"blockedLeafWrites": 114,
|
||||||
"rngWords": 16,
|
"rngWords": 16,
|
||||||
"rngLoaded": true,
|
"rngLoaded": true,
|
||||||
"rngCommitted": false,
|
"rngCommitted": false,
|
||||||
|
|
@ -1205,8 +1207,8 @@
|
||||||
"driver": "StrategyServer::ProcessTurn",
|
"driver": "StrategyServer::ProcessTurn",
|
||||||
"id": "S04",
|
"id": "S04",
|
||||||
"name": "RebuildAllianceMasks",
|
"name": "RebuildAllianceMasks",
|
||||||
"status": "stub",
|
"status": "implemented",
|
||||||
"ran": 0,
|
"ran": 8,
|
||||||
"writes": 0,
|
"writes": 0,
|
||||||
"blockedWrites": 0,
|
"blockedWrites": 0,
|
||||||
"rng": 0
|
"rng": 0
|
||||||
|
|
@ -1968,7 +1970,7 @@
|
||||||
"status": "blocked",
|
"status": "blocked",
|
||||||
"ran": 8,
|
"ran": 8,
|
||||||
"writes": 0,
|
"writes": 0,
|
||||||
"blockedWrites": 48,
|
"blockedWrites": 104,
|
||||||
"rng": 0
|
"rng": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
||||||
142
verify/results/standalone/t36-turnrecord.md
Normal file
142
verify/results/standalone/t36-turnrecord.md
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
# T36 `FinalizeTurnRecords` — the ship census wired in, and what T36 is still blocked on
|
||||||
|
|
||||||
|
Lane E2, 2026-09-08. Engine branch `wip/turnrecord` off `sots-engine` main `0592104`.
|
||||||
|
Measured with `verify/state-checksum/state_checksum.py` leaves, the same currency as
|
||||||
|
`report.txt`. **`closed` and `regressed` are reported separately on every line; nothing here
|
||||||
|
is netted.**
|
||||||
|
|
||||||
|
`status.json` and `report.txt` in this directory were regenerated from the same binary.
|
||||||
|
|
||||||
|
## What changed in the engine
|
||||||
|
|
||||||
|
`ShipCensus` (lane D2) is wired into `BuildTurnRecord`. The classification walks every
|
||||||
|
player's designs — normal and legacy, one id space — resolves each design's sections against
|
||||||
|
the section catalog, and walks the global fleet list keyed by `Flt.PID` against each player's
|
||||||
|
**object id**, not its vector position. The record's modelled field count goes 7 → 13.
|
||||||
|
|
||||||
|
Two things the standalone did not have before:
|
||||||
|
|
||||||
|
* **a data root.** The census cannot come from a save: a design's hull size and its
|
||||||
|
defence-platform flag are recomputed from the section catalog whenever the design changes
|
||||||
|
and are never written down. `sots_turn --data DIR` (or `$SOTS_DATA_DIR`) supplies it. No
|
||||||
|
game data enters the repo, and without a root the six counters are reported unmodelled
|
||||||
|
rather than written as six zeros.
|
||||||
|
* **`--commit-blocked=IDS` / `--commit-blocked-except=IDS`.** `--commit-blocked` alone is
|
||||||
|
all-or-nothing across every blocked phase, which reports one closed count and one regressed
|
||||||
|
count for all of them together — the netting the campaign does not do. The two lists narrow
|
||||||
|
it to named phase ids, so a phase's own contribution can be measured. Every number below
|
||||||
|
that names T36 was measured with `--commit-blocked=T36`.
|
||||||
|
|
||||||
|
## Prediction, written before the code (rule 2)
|
||||||
|
|
||||||
|
> Default mode unchanged at 209 → 204, closed 5 / regressed 0 and 108 → 103, closed 5 /
|
||||||
|
> regressed 0. With `--commit-blocked`, the three census leaves close and the regressed list
|
||||||
|
> falls from 9 to 6 on pair 1 (`inc`×3 + `sav`×3, the budget) and from 11 to 8 on pair 2.
|
||||||
|
|
||||||
|
Falsification hypothesis 1 was: *the census is built from the fleet list as it stands, which
|
||||||
|
is pre-construction; if a real turn's census differs from the input turn's, the leaf does not
|
||||||
|
close and shows a third value.*
|
||||||
|
|
||||||
|
**That is what happened.** Two of the three closed; the third did not, and the symptom was
|
||||||
|
exactly the one written down.
|
||||||
|
|
||||||
|
## Measured — reference pair `turn1-state.sav` → `turn2-state.sav`
|
||||||
|
|
||||||
|
| run | closed | regressed |
|
||||||
|
|---|---:|---:|
|
||||||
|
| default (no commit flags) — before and after this lane | 5 | 0 |
|
||||||
|
| `--commit-blocked`, before this lane | 29 | 9 |
|
||||||
|
| `--commit-blocked`, after | 29 | **7** |
|
||||||
|
| `--commit-blocked=T36` alone, with a data root | 29 | 7 |
|
||||||
|
| `--commit-blocked=T36` alone, no data root | 29 | 9 |
|
||||||
|
|
||||||
|
Regressed after, named: `hist[0]/stats[1]/{sav,inc}`, `hist[1]/stats[1]/{sav,inc}`,
|
||||||
|
`hist[7]/stats[1]/{sav,inc}` — the budget, lane E1 — and `hist[1]/stats[1]/shpt[0]`, ours 0,
|
||||||
|
archived 1.
|
||||||
|
|
||||||
|
Closed by the census: `hist[4]/stats[1]/shpt[2]` (5 dreadnoughts) and
|
||||||
|
`hist[7]/stats[1]/satt[0]` (10 defence platforms).
|
||||||
|
|
||||||
|
## Measured — second pair `turn2-state.sav` → `turn3-state.sav`
|
||||||
|
|
||||||
|
| run | closed | regressed |
|
||||||
|
|---|---:|---:|
|
||||||
|
| default | 5 | 0 |
|
||||||
|
| `--commit-blocked`, before this lane | 13 | 11 |
|
||||||
|
| `--commit-blocked`, after | 13 | **9** |
|
||||||
|
| `--commit-blocked=T36` alone, with a data root | 13 | 7 |
|
||||||
|
| `--commit-blocked=T36` alone, no data root | 13 | 9 |
|
||||||
|
|
||||||
|
The two extra regressions under a full `--commit-blocked` are `Player/Status` on two players.
|
||||||
|
They are S31's, not T36's, and the new id filter separates them cleanly — which is the whole
|
||||||
|
reason the filter exists.
|
||||||
|
|
||||||
|
## The one census leaf that did not close is not a census error
|
||||||
|
|
||||||
|
`app_test_turn_record`, extended this lane, now compares the six counters against the record
|
||||||
|
the game itself archived, on every save: **11 saves, 80 player-records, 1040 fields, 480 of
|
||||||
|
them census leaves, 0 mismatches.** That is the same 480/480 lane D2 got, reproduced through
|
||||||
|
the app's own code path (which visits slots in the original's in-memory order rather than the
|
||||||
|
wire's) rather than through D2's test.
|
||||||
|
|
||||||
|
So the model reproduces the archived census exactly for the turn the save was written at. The
|
||||||
|
remaining leaf is `shpt[0]` for one player, and the archived value is higher than ours by
|
||||||
|
exactly one destroyer on **both** pairs (0 vs 1, then 1 vs 2). That player's build queue
|
||||||
|
completes one ship per turn, and no phase the standalone runs creates a ship — S11's
|
||||||
|
build-queue sub-pass is the declared input boundary. The leaf is short by the turn's
|
||||||
|
construction, not wrong about classification.
|
||||||
|
|
||||||
|
**This is a new named blocker, and it is not lane E1's and not mine.**
|
||||||
|
|
||||||
|
## T36's status: still `Blocked`, on two named things, neither of them in this phase
|
||||||
|
|
||||||
|
1. `sav` and `inc` for the new turn come from P01/P02, blocked on the per-system money
|
||||||
|
output — **lane E1**.
|
||||||
|
2. `shpt[0]` is short by the ships the turn builds — **ship construction, unmodelled**.
|
||||||
|
|
||||||
|
There is **no field-granular knob that could rescue this**, and the brief's
|
||||||
|
`--commit-blocked-except=<fields>` idea is not implementable as stated: the archived record
|
||||||
|
is one struct on the wire, so `sav` and `inc` cannot be left out while the other eleven fields
|
||||||
|
are written. The format has no hole. Committing is all-or-nothing at the record, so the
|
||||||
|
choice is 29 closed with 7 confidently-wrong leaves, or neither — and 7 wrong leaves is not
|
||||||
|
worth 29 that a later lane closes for free. What *is* implementable, and is implemented, is
|
||||||
|
the same convention at **phase** granularity, which is what produced the isolated rows above.
|
||||||
|
|
||||||
|
T36 flips the moment E1 lands, minus one leaf that waits on construction.
|
||||||
|
|
||||||
|
## Coverage, stated as loudly as the verdict (rules 6 and 15)
|
||||||
|
|
||||||
|
Only **32 of the 480** archived census leaves are nonzero anywhere in the 11-save corpus.
|
||||||
|
Per leaf (cls0 shpt/satt, cls1 shpt/satt, cls2 shpt/satt) = **18/3, 0/0, 11/0**.
|
||||||
|
|
||||||
|
* **cls1 (cruisers), ships and platforms both, and `satt` for cls2, have never been observed
|
||||||
|
nonzero.** Three of the six counters are unexercised hypotheses, not verified. A zero leaf
|
||||||
|
agrees for free. The corpus needs a cruiser and a dreadnought-hull platform
|
||||||
|
(roadmap §5 already lists both).
|
||||||
|
* The other four words of each class group — `shpl`, `shpk`, `satl`, `satk`, losses and kills
|
||||||
|
— are zero throughout the corpus, and this phase writes zeros with no model behind them.
|
||||||
|
Listed in the phase's own unmodelled list rather than passed off as agreement.
|
||||||
|
* Hull size is an **assignment** in slot order, so the visit order is load-bearing in
|
||||||
|
principle. The original's stats pass walks mission, command, engine; the wire writes
|
||||||
|
command, mission, engine. This code reproduces the memory order. **Design rule A6 makes
|
||||||
|
every shipped design class-homogeneous, so no save in the corpus can tell the two orders
|
||||||
|
apart** — the order is carried from the instruction stream, not confirmed by these bytes.
|
||||||
|
* `verified` stays **0**. Nothing here was compared against a running game; this lane holds no
|
||||||
|
VM. The comparison is against bytes the original wrote, which is the strongest check
|
||||||
|
available without one, and it is not the same thing.
|
||||||
|
|
||||||
|
## Gates
|
||||||
|
|
||||||
|
Run as separate commands, never chained (rule 13):
|
||||||
|
|
||||||
|
* `tools/clean_room_check.sh` — OK
|
||||||
|
* host `ctest`, no `SOTS_SAVES_DIR` — 45/45
|
||||||
|
* host `ctest`, `SOTS_SAVES_DIR` set — 45/45
|
||||||
|
* host `ctest`, `SOTS_SAVES_DIR` + `SOTS_DATA_DIR` set — 44/45. The one failure is
|
||||||
|
`game_data_realdata`, and it **fails identically on unmodified `main`** with the same data
|
||||||
|
root: that test pins section and bank counts against the campaign's canonical extraction and
|
||||||
|
my extraction of `sots.gob` is a different data version (9 pinned counts differ, e.g. a
|
||||||
|
`human/DEWAR` section the pin says should be absent). It is a data-root mismatch, not a
|
||||||
|
regression, and the census matched all 480 archived leaves against that same root anyway.
|
||||||
|
* **Shim cross-build NOT run**: no `i686-w64-mingw32-g++` on this host. No `src/shim` file was
|
||||||
|
touched, but per rule 13 the integrator should run the CT111 shim build before pushing.
|
||||||
Loading…
Add table
Reference in a new issue