plan: pivot to displacement; gate.sh replaces the hollow gate; Rung B worklist from lane CV
This commit is contained in:
parent
c4ea347ace
commit
b6018a0f19
4 changed files with 170 additions and 15 deletions
|
|
@ -1,17 +1,17 @@
|
|||
# SotS RE campaign — coverage dashboard
|
||||
|
||||
Generated 2026-09-09 08:13 UTC · `sots-re` @ d46b3f8,2026-09-09 · `sots-engine` @ e7e2bd6,2026-09-09 (245 commits) · regenerate with `tools/dashboard.py`
|
||||
Generated 2026-09-09 13:40 UTC · `sots-re` @ c4ea347,2026-09-09 · `sots-engine` @ e7e2bd6,2026-09-09 (245 commits) · regenerate with `tools/dashboard.py`
|
||||
|
||||
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
||||
|
||||
## 1. Map coverage (campaign/board.md)
|
||||
|
||||
444 targets · mapped-or-better **396/444** `[█████████░] 89%` · verified **354/444** `[████████░░] 80%`
|
||||
447 targets · mapped-or-better **399/447** `[█████████░] 89%` · verified **356/447** `[████████░░] 80%`
|
||||
|
||||
| Status | Count | % |
|
||||
|---|---:|---:|
|
||||
| verified | 354 | 80% |
|
||||
| mapped | 42 | 9% |
|
||||
| verified | 356 | 80% |
|
||||
| mapped | 43 | 10% |
|
||||
| in-progress | 5 | 1% |
|
||||
| backlog | 41 | 9% |
|
||||
| blocked | 2 | 0% |
|
||||
|
|
@ -21,17 +21,17 @@ Generated 2026-09-09 08:13 UTC · `sots-re` @ d46b3f8,2026-09-09 · `sots-engine
|
|||
| objects | 46 | 6 | 0 | 3 | 1 | 56 |
|
||||
| control-flow | 41 | 2 | 1 | 0 | 0 | 44 |
|
||||
| subsystems | 4 | 8 | 0 | 2 | 1 | 15 |
|
||||
| engine | 32 | 0 | 0 | 0 | 0 | 32 |
|
||||
| engine | 33 | 1 | 0 | 0 | 0 | 34 |
|
||||
| verify | 105 | 15 | 3 | 35 | 0 | 158 |
|
||||
| phase2 | 13 | 3 | 1 | 0 | 0 | 17 |
|
||||
| meta | 93 | 6 | 0 | 1 | 0 | 100 |
|
||||
| meta | 94 | 6 | 0 | 1 | 0 | 101 |
|
||||
| other | 20 | 2 | 0 | 0 | 0 | 22 |
|
||||
|
||||
## 2. Binary understanding
|
||||
|
||||
- RTTI type descriptors: **1,924** (`Game::` 1,404, `Mars::` 194; serializable types 179)
|
||||
- Classes with recovered member layouts: **384** / 1,598 named classes `[██░░░░░░░░] 24%` — `objects/layouts.json` (serializer recovery) plus classes recovered by hand in `struct-recovery.md` + `schema-gaps-resolved.md`. Note 179 types are *serializable*; the recovery also reaches non-serializable ones, so this is not a subset of that
|
||||
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **1294**, verified **1163** `[█████████░] 90%`
|
||||
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **1298**, verified **1167** `[█████████░] 90%`
|
||||
|
||||
## 3. Data layer
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ Generated 2026-09-09 08:13 UTC · `sots-re` @ d46b3f8,2026-09-09 · `sots-engine
|
|||
| `shim/trace` | 2,258 | 9 | 273 | direct (WIN32) | shim-trace.md |
|
||||
| **total** | **59,514** | **122** | **4257** | | |
|
||||
|
||||
Board `engine:` rows: verified **32**, mapped 0, in flight 0 (of 32) — verified & merged `[██████████] 100%`
|
||||
Board `engine:` rows: verified **33**, mapped 1, in flight 0 (of 34) — verified & merged `[██████████] 97%`
|
||||
|
||||
## 5. Phase 2 milestones
|
||||
|
||||
|
|
@ -121,7 +121,7 @@ Detail: `verify/results/standalone/report.txt`.
|
|||
|
||||
## 8. Open questions
|
||||
|
||||
Open **26** · resolved/parked 11 · backlog items: 1. The engine today 0, 2. The milestone, restated 5, 3. Engine work to Rung A 0, 4. Future engine modules 5, 5. Workloads to manufacture 7, 6. Multiplayer revival 4, 7. Method and infrastructure 5, Parked 2
|
||||
Open **26** · resolved/parked 11 · backlog items: 1. The engine today 0, 2. The milestone, restated — 2026-09-09 7, 2-old. The milestone as restated 2026-09-08 5, 3. The plan — three tracks, in priority order 0, 4. Future engine modules 5, 5. Workloads to manufacture 7, 6. Multiplayer revival 4, 7. Method and infrastructure 5, Parked 2
|
||||
|
||||
Most recent open:
|
||||
|
||||
|
|
@ -133,11 +133,11 @@ Most recent open:
|
|||
|
||||
## 9. Delta since previous dashboard
|
||||
|
||||
- verified targets: 353 → 354 (+1) · mapped-or-better: 395 → 396 (+1)
|
||||
- engine LOC: 59,504 → 59,514 (+10) · test files: 122 → 122 (+0) · checks: 4,257 → 4,257 (+0)
|
||||
- addresses verified: 1,163 → 1,163 (+0) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||
- verified targets: 354 → 356 (+2) · mapped-or-better: 396 → 399 (+3)
|
||||
- engine LOC: 59,514 → 59,514 (+0) · test files: 122 → 122 (+0) · checks: 4,257 → 4,257 (+0)
|
||||
- addresses verified: 1,163 → 1,167 (+4) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||
- standalone leaves closed: 45 → 45 (+0) · leaves still diverging: 63 → 63 (+0)
|
||||
|
||||
---
|
||||
warnings: board.md: unknown types subsystems, tooling; mars-rng.md: no oracle total row parsed; mars-stream.md: no oracle total row parsed; mars-vfs.md: no oracle total row parsed
|
||||
<!-- dashboard-metrics {"verified": 354, "mapped_plus": 396, "targets": 444, "loc": 59514, "tests": 122, "checks": 4257, "addr_verified": 1163, "addr_total": 1294, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
||||
<!-- dashboard-metrics {"verified": 356, "mapped_plus": 399, "targets": 447, "loc": 59514, "tests": 122, "checks": 4257, "addr_verified": 1167, "addr_total": 1298, "layouts": 384, "open_q": 26, "sa_closed": 45, "sa_left": 63} -->
|
||||
|
|
|
|||
|
|
@ -25,7 +25,51 @@ run the economy/research/movement/output pieces to the original's numbers, and s
|
|||
**16 of 44** driver phases and **5 of 37** tail phases modelled (10 committed). It cannot yet
|
||||
reproduce a turn.
|
||||
|
||||
## 2. The milestone, restated (again — 2026-09-08 evening)
|
||||
## 2. The milestone, restated — 2026-09-09 (after the determinism arc)
|
||||
|
||||
> `sots_turn` loads a save, runs one strategic turn, and writes an autosave that byte-matches
|
||||
> the original's — **for a stated procedure and route**.
|
||||
|
||||
Two days of lanes went into determinism and the foundation is now laid. What is *measured*:
|
||||
|
||||
- **The sim is deterministic given the command stream.** Every draw of a turn attributed by
|
||||
return address; the strategic generator's residual is 0 on every measured turn.
|
||||
- **The AI is deterministic given (seeds, visit order).** Its per-process seed is one word per
|
||||
client, minted from the global generator — which does *nothing else* on an encounter-free turn.
|
||||
Pinning the seeds collapses a rich turn's divergence from 94 leaves to **one transposition**, and
|
||||
that transposition is the **order of two heap pointers**: the fleet-assignment pass walks a
|
||||
container keyed on `fleet->Location`. There is **no original order to match**; we choose one
|
||||
member of its outcome set and say so (`orders.h`). The visit order is *written into the block*
|
||||
(list 10), so a captured run carries its own.
|
||||
- **The route is part of the procedure.** The same turn reached by continuation and by load gives
|
||||
different, individually reproducible results, because a `Colonize` task alive in the AI agent by
|
||||
continuation is *absent* after a load. Certified pairs live in `verify/results/saves/certified-pairs.md`
|
||||
as `(save, procedure, route, hashes, processes, masks)`; a hash without its route is not a claim.
|
||||
- **Exposure is a screen, not a decision procedure** (rule 26(c)): it says a control is *likely* to
|
||||
vary; it cannot certify one will agree.
|
||||
|
||||
**So the rungs stand as written below, with one scope line each:**
|
||||
|
||||
- **Rung A** — byte-match modulo the command stream, **on a load→turn procedure**. Canonical pair
|
||||
`ref-turn2 → turn3`. 204 leaves open; the RE for them is done (§3-old items 1b/1c/7).
|
||||
- **Rung B** — byte-match given the recorded stream. **Climbed to outcome 3 on the first rich turn
|
||||
(lane CV):** the replay runs and consumes the whole stream; the result is a **ranked leaf list of
|
||||
thirteen named subsystems, zero ungrouped** — 1,092 leaves. Two blockers sit *upstream* of the
|
||||
turn (§3, track 0). The tail's sim draw fires on this workload (`tscr = 253`), so Rung B needs
|
||||
the same generator model as Rung A — that correction is load-bearing here.
|
||||
- **Rung C** — `game/ai` deterministic given (save, seeds, visit order). **C-exact survives
|
||||
literally** on that basis; the comparison side (`--relabel-new-ids`) ships with both acceptance
|
||||
halves. The engine side is not built: `game/ai` mints no fleet ids yet.
|
||||
|
||||
**What stops now.** Further RNG/determinism lanes, unless a rung is actually blocked by one. Board
|
||||
row count as a success signal — 89% of 444 rows measures campaign activity, not the product. The
|
||||
value-domain census as a work generator — it is a screen; use it when a lane needs a corpus count.
|
||||
|
||||
**What the headline is.** Displacement (`tools/displacement.py`): **3 replaced / 7 compared /
|
||||
7 modelled / 3 mapped**, unmoved for two days. And the phase catalogue: 14 of 44 driver phases,
|
||||
2 of 37 tail. Those two numbers are the product.
|
||||
|
||||
## 2-old. The milestone as restated 2026-09-08 (kept for the record)
|
||||
|
||||
> `sots_turn` loads a save, runs one strategic turn, and writes an autosave that byte-matches
|
||||
> the original's.
|
||||
|
|
@ -87,7 +131,52 @@ candidate walk (lane L4) — the other two are stream-insensitive **by code path
|
|||
Rung B is unaffected: `--turn-commands` replay stays the no-AI path, and the canonical pair stays
|
||||
`turn2-state → turn3-state` until the pin probe promotes the creation turn.
|
||||
|
||||
## 3. Engine work to Rung A (ranked by leaves closed per lane)
|
||||
## 3. The plan — three tracks, in priority order
|
||||
|
||||
### Track 0 — make the gate honest, then clear the two upstream blockers
|
||||
|
||||
The gate reported 59/59 for a day while the corpus tests **skipped** (`SOTS_SAVES_DIR` unset on
|
||||
CT111). With the corpus it is **57/59**: the coverage ratchet broke when the corpus grew 22 → 43
|
||||
(rule 27, as designed), and a writer defect appeared. `tools/gate.sh --fresh` is now the gate and
|
||||
it fails if a corpus test skips.
|
||||
|
||||
| # | item | module | evidence | why first |
|
||||
|---|---|---|---|---|
|
||||
| 0a | **`ProjectName` reads `usnc` as one item; the wire is a `usp`/`usc` pair.** 12 of 43 saves round-trip 12 bytes short. | `mars/stream` | lane CV; `ad-turn27` has `usnc == 1` | no byte-match claim is possible on the `ad-*`/`ar-*` family until the writer is exact; re-prove byte-neutrality after |
|
||||
| 0b | **Re-type what the ratchet caught** — the spy saves (`ap-*`) and whatever else dropped `pct` below 99.99. | `mars/stream` | `tools/gate.sh` output | the ratchet did its job; honour it |
|
||||
| 0c | **List-5 applier cannot fire** because the memory capture cannot type 7 of 8 fields. One UI run (two sliders, two values) settles it. | shim capture | lane CV | the only list with an applier, at zero |
|
||||
|
||||
### Track 1 — displacement: `compared → replaced`, then `modelled → compared`
|
||||
|
||||
Only `replaced` means the original's code did not run. The bar, written once: an un-instrumented
|
||||
oracle first (`certified-pairs.md` format), then the same procedure with the hook in `replace`
|
||||
mode and the **same hashes**, with a count from the hook proving the path executed (rule 1).
|
||||
|
||||
| # | module | today | evidence for the attempt | target |
|
||||
|---|---|---|---|---|
|
||||
| 1a | `TechTree::ProcessResearch` + unlock cascade | compared | 35 calls / 3 workloads / 0 div; advance prediction held on a changed workload | **replaced** — lane CR running |
|
||||
| 1b | `ServerSystem::ComputeTotalOutput` + `GroupOutput` | compared | 24,357 calls, 0 undeclared writes — but **13 distinct states** (rule 23) | replaced, after widening the state set |
|
||||
| 1c | `ServerSystem::ProcessTurn` (colony) | compared | 36 calls 0 div; 3 owned systems, gates all zero | replaced, on a save with gate traffic |
|
||||
| 1d | `game/nav`, `game/design`, `game/combat` retreat, `mars/vfs` | modelled, **never hooked** | host-tested only | compared — one lane each |
|
||||
|
||||
### Track 2 — Rung B worklist, ranked against a real rich turn (lane CV, residual 0)
|
||||
|
||||
| leaves | subsystem | note |
|
||||
|---:|---|---|
|
||||
| 539 | morale event ring `cme2` | **not a module** — a fixed 11-slot ring shifted by 27 appended events of three kinds (colonisation, savings band, population). It is the reporting surface of the next three rows and closes when they do |
|
||||
| 154 | colony growth / repair / bonuses | §3-old 1b/1c — `Pv*` is **mixed**: `PvPop`/`PvInfra` hold the uncapped projection, `PvSuit`/`PvRes` the pre-turn current |
|
||||
| 150 | fleet objects | needs the gather/mint (Rung C engine side) |
|
||||
| **79** | **`T34 RecordObservedDesigns`** | **largest independently closable stub, no upstream dependency — do this one first** |
|
||||
| 30 | player money + counters | §3-old item 1 chain |
|
||||
| 23 | `TShn` | watchpoint specified (§3-old 4) |
|
||||
| 23 | system↔fleet membership | with fleet objects |
|
||||
| 20 / 20 / 15 / 13 / 10 / 8 / 6 | ShipRecs · build queues · other system · crep/CD · id lists+generator · turnstats · trade manager | |
|
||||
| 5 of 6 regressions | one `ntdev` predicate | cheapest fix in the list |
|
||||
|
||||
`ModCount` residual 2 is localised to lists 1/7/12; the only uniform reading is list 7 at 2 bumps —
|
||||
a prediction fitted to one observation, falsified by any capture with a colonize count ≠ 2.
|
||||
|
||||
### §3-old — Rung A leaf ranking (still valid for the items it names)
|
||||
|
||||
| # | engine deliverable | module | RE input (done unless noted) | closes |
|
||||
|---|---|---|---|---|
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
63
tools/gate.sh
Executable file
63
tools/gate.sh
Executable file
|
|
@ -0,0 +1,63 @@
|
|||
#!/usr/bin/env bash
|
||||
# The engine gate, as a script instead of as the integrator's memory.
|
||||
#
|
||||
# Why this exists: for a whole day the gate reported 59/59 while the two tests that read
|
||||
# the save corpus were SKIPPING, because SOTS_SAVES_DIR was never set on CT111. The corpus
|
||||
# had grown from 22 to 43 saves and the coverage ratchet had broken exactly as rule 27 says
|
||||
# it should -- and a writer defect had appeared on 12 of them -- and the gate could not see
|
||||
# either. A green verdict on a harness that is comparing nothing (rule 1), delivered by the
|
||||
# person whose job was to notice it.
|
||||
#
|
||||
# Each check is its own command and its own exit code. Nothing here is &&-chained across
|
||||
# checks, because a chain that short-circuits reports a check that never ran (rule 22's
|
||||
# cousin, paid for once already).
|
||||
#
|
||||
# Usage: tools/gate.sh [--fresh] --fresh: rm -rf the remote build dirs first (rule 24)
|
||||
set -u
|
||||
|
||||
ENGINE="${ENGINE:-$HOME/sots-engine}"
|
||||
RE="${RE:-$HOME/sots-re}"
|
||||
CT=111
|
||||
REMOTE_TREE=/srv/re-lab/build/sots-engine
|
||||
REMOTE_CORPUS=/srv/re-lab/saves-corpus
|
||||
FRESH=0
|
||||
[ "${1:-}" = "--fresh" ] && FRESH=1
|
||||
|
||||
ct() { ssh spicy "pct exec $CT -- bash -lc '$*'"; }
|
||||
|
||||
status=0
|
||||
report() { # name rc
|
||||
if [ "$2" -eq 0 ]; then echo "GATE ok $1"; else echo "GATE FAIL $1 (exit $2)"; status=1; fi
|
||||
}
|
||||
|
||||
echo "== gate: $ENGINE @ $(git -C "$ENGINE" rev-parse --short HEAD), corpus $(ls "$RE"/verify/results/saves/*.sav | wc -l) saves, fresh=$FRESH"
|
||||
|
||||
# 1. clean-room, host
|
||||
( cd "$ENGINE" && bash tools/clean_room_check.sh ); report clean-room $?
|
||||
|
||||
# 2. shim config structure, host
|
||||
( cd "$ENGINE" && uv run --quiet python3 tools/check_shim_configs.py ); report shim-configs $?
|
||||
|
||||
# 3. sync the tree -- BOTH halves of rule 24: exclude local build dirs, and clear the remote ones
|
||||
rsync -a --delete --exclude '.git' --exclude 'build*' -e ssh "$ENGINE"/ spicy:/tmp/eng-gate/; report sync-to-host $?
|
||||
if [ $FRESH -eq 1 ]; then ct "rm -rf $REMOTE_TREE/build-host $REMOTE_TREE/build-shim"; report clear-remote-builds $?; fi
|
||||
ssh spicy "tar -C /tmp/eng-gate -cf - . | pct exec $CT -- tar -C $REMOTE_TREE -xf -"; report sync-to-ct $?
|
||||
|
||||
# 4. sync the corpus -- the tests are only a gate if they run against it
|
||||
rsync -a --delete --include='*.sav' --exclude='*' -e ssh "$RE"/verify/results/saves/ spicy:/tmp/sots-corpus/; report corpus-to-host $?
|
||||
ssh spicy "pct exec $CT -- mkdir -p $REMOTE_CORPUS && tar -C /tmp/sots-corpus -cf - . | pct exec $CT -- tar -C $REMOTE_CORPUS -xf -"; report corpus-to-ct $?
|
||||
NCORPUS=$(ct "ls $REMOTE_CORPUS | grep -c .sav")
|
||||
echo "GATE info corpus on CT111: $NCORPUS saves"
|
||||
|
||||
# 5. host build + tests, WITH the corpus
|
||||
ct "cd $REMOTE_TREE && cmake -S . -B build-host -DCMAKE_BUILD_TYPE=Release >/dev/null 2>&1 && cmake --build build-host -j8 2>&1 | tail -1"; report host-build $?
|
||||
ct "cd $REMOTE_TREE/build-host && SOTS_SAVES_DIR=$REMOTE_CORPUS ctest --output-on-failure 2>&1 | tail -15"; report host-ctest $?
|
||||
# and prove the corpus tests RAN rather than skipped
|
||||
SKIPPED=$(ct "cd $REMOTE_TREE/build-host && SOTS_SAVES_DIR=$REMOTE_CORPUS ctest -V 2>&1 | grep -c 'unset, skipped'")
|
||||
if [ "${SKIPPED:-1}" -ne 0 ]; then echo "GATE FAIL corpus tests skipped ($SKIPPED) -- the gate is hollow"; status=1; else echo "GATE ok corpus tests ran (0 skipped)"; fi
|
||||
|
||||
# 6. shim cross-build
|
||||
ct "cd $REMOTE_TREE && cmake -S . -B build-shim -DCMAKE_TOOLCHAIN_FILE=cmake/toolchain-mingw-i686.cmake -DCMAKE_BUILD_TYPE=Release >/dev/null 2>&1 && cmake --build build-shim -j8 2>&1 | tail -1 && ls -la build-shim/binkw32.dll"; report shim-cross-build $?
|
||||
|
||||
echo "== gate: $([ $status -eq 0 ] && echo GREEN || echo RED)"
|
||||
exit $status
|
||||
Loading…
Add table
Reference in a new issue