Compare commits
2 commits
619edf97f4
...
84d5609af8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84d5609af8 | ||
|
|
3b5eca29a2 |
3 changed files with 104 additions and 19 deletions
|
|
@ -1,30 +1,30 @@
|
||||||
# SotS RE campaign — coverage dashboard
|
# SotS RE campaign — coverage dashboard
|
||||||
|
|
||||||
Generated 2026-09-08 05:30 UTC · `sots-re` @ cdada28,2026-09-08 · `sots-engine` @ e1cbb81,2026-09-08 (65 commits) · regenerate with `tools/dashboard.py`
|
Generated 2026-09-08 06:13 UTC · `sots-re` @ 3b5eca2,2026-09-08 · `sots-engine` @ 7584bad,2026-09-08 (68 commits) · regenerate with `tools/dashboard.py`
|
||||||
|
|
||||||
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
||||||
|
|
||||||
## 1. Map coverage (campaign/board.md)
|
## 1. Map coverage (campaign/board.md)
|
||||||
|
|
||||||
63 targets · mapped-or-better **48/63** `[████████░░] 76%` · verified **31/63** `[█████░░░░░] 49%`
|
65 targets · mapped-or-better **50/65** `[████████░░] 77%` · verified **33/65** `[█████░░░░░] 51%`
|
||||||
|
|
||||||
| Status | Count | % |
|
| Status | Count | % |
|
||||||
|---|---:|---:|
|
|---|---:|---:|
|
||||||
| verified | 31 | 49% |
|
| verified | 33 | 51% |
|
||||||
| mapped | 17 | 27% |
|
| mapped | 17 | 26% |
|
||||||
| in-progress | 1 | 2% |
|
| in-progress | 3 | 5% |
|
||||||
| backlog | 12 | 19% |
|
| backlog | 11 | 17% |
|
||||||
| blocked | 1 | 2% |
|
| blocked | 1 | 2% |
|
||||||
|
|
||||||
| Type | verified | mapped | in-progress | backlog | blocked | total |
|
| Type | verified | mapped | in-progress | backlog | blocked | total |
|
||||||
|---|---:|---:|---:|---:|---:|---:|
|
|---|---:|---:|---:|---:|---:|---:|
|
||||||
| objects | 5 | 2 | 0 | 0 | 0 | 7 |
|
| objects | 5 | 2 | 0 | 0 | 0 | 7 |
|
||||||
| control-flow | 0 | 2 | 0 | 0 | 0 | 2 |
|
| control-flow | 0 | 2 | 0 | 0 | 0 | 2 |
|
||||||
| subsystems | 2 | 6 | 1 | 3 | 1 | 13 |
|
| subsystems | 2 | 6 | 2 | 3 | 1 | 14 |
|
||||||
| engine | 10 | 0 | 0 | 0 | 0 | 10 |
|
| engine | 10 | 0 | 0 | 0 | 0 | 10 |
|
||||||
| verify | 5 | 2 | 0 | 6 | 0 | 13 |
|
| verify | 5 | 2 | 1 | 5 | 0 | 13 |
|
||||||
| phase2 | 5 | 1 | 0 | 2 | 0 | 9 |
|
| phase2 | 6 | 1 | 0 | 2 | 0 | 9 |
|
||||||
| meta | 4 | 4 | 0 | 1 | 0 | 9 |
|
| meta | 5 | 4 | 0 | 1 | 0 | 10 |
|
||||||
|
|
||||||
## 2. Binary understanding
|
## 2. Binary understanding
|
||||||
|
|
||||||
|
|
@ -54,10 +54,10 @@ Generated 2026-09-08 05:30 UTC · `sots-re` @ cdada28,2026-09-08 · `sots-engine
|
||||||
| `mars/stream` | 3,703 | 6 | 222 | yes | mars-stream.md |
|
| `mars/stream` | 3,703 | 6 | 222 | yes | mars-stream.md |
|
||||||
| `mars/text` | 899 | 8 | 245 | yes | mars-text.md |
|
| `mars/text` | 899 | 8 | 245 | yes | mars-text.md |
|
||||||
| `mars/vfs` | 788 | 9 | 140 | yes | mars-vfs.md |
|
| `mars/vfs` | 788 | 9 | 140 | yes | mars-vfs.md |
|
||||||
| `shim` | 7,551 | 0 | 0 | direct (WIN32) | M0.md |
|
| `shim` | 7,620 | 0 | 0 | direct (WIN32) | M0.md |
|
||||||
| `shim/hooks` | 4,981 | 0 | 0 | direct (WIN32) | M0.md |
|
| `shim/hooks` | 5,050 | 0 | 0 | direct (WIN32) | M0.md |
|
||||||
| `shim/trace` | 2,258 | 9 | 273 | direct (WIN32) | shim-trace.md |
|
| `shim/trace` | 2,258 | 9 | 273 | direct (WIN32) | shim-trace.md |
|
||||||
| **total** | **28,506** | **89** | **2830** | | |
|
| **total** | **28,644** | **89** | **2830** | | |
|
||||||
|
|
||||||
Board `engine:` rows: verified **10**, mapped 0, in flight 0 (of 10) — verified & merged `[██████████] 100%`
|
Board `engine:` rows: verified **10**, mapped 0, in flight 0 (of 10) — verified & merged `[██████████] 100%`
|
||||||
|
|
||||||
|
|
@ -94,10 +94,10 @@ Most recent open:
|
||||||
|
|
||||||
## 8. Delta since previous dashboard
|
## 8. Delta since previous dashboard
|
||||||
|
|
||||||
- verified targets: 30 → 31 (+1) · mapped-or-better: 47 → 48 (+1)
|
- verified targets: 33 → 33 (+0) · mapped-or-better: 50 → 50 (+0)
|
||||||
- engine LOC: 26,883 → 28,506 (+1,623) · test files: 88 → 89 (+1) · checks: 2,805 → 2,830 (+25)
|
- engine LOC: 28,644 → 28,644 (+0) · test files: 89 → 89 (+0) · checks: 2,830 → 2,830 (+0)
|
||||||
- addresses verified: 317 → 317 (+0) · recovered layouts: 21 → 21 (+0) · open questions: 27 → 27 (+0)
|
- addresses verified: 317 → 317 (+0) · recovered layouts: 21 → 21 (+0) · open questions: 27 → 27 (+0)
|
||||||
|
|
||||||
---
|
---
|
||||||
warnings: board.md line 66: unknown status 'code-complete' for 'P2-B4 colony + movement (behavioral)'; mars-rng.md: no oracle total row parsed; mars-stream.md: no oracle total row parsed; mars-vfs.md: no oracle total row parsed
|
warnings: 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": 31, "mapped_plus": 48, "targets": 63, "loc": 28506, "tests": 89, "checks": 2830, "addr_verified": 317, "addr_total": 324, "layouts": 21, "open_q": 27} -->
|
<!-- dashboard-metrics {"verified": 33, "mapped_plus": 50, "targets": 65, "loc": 28644, "tests": 89, "checks": 2830, "addr_verified": 317, "addr_total": 324, "layouts": 21, "open_q": 27} -->
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`).
|
||||||
| P2-B3 ProcessResearch (behavioral, RNG) | phase2 | mapped | high | 85% | 2026-09-08 | LIVE, PARTIAL PASS: 15 calls compared, 13 zero-divergence; RNG post-state matched 14/15 incl. every roll (validates MT19937 + draw mapping + odds together). 2 divergences are the declared SetResearched boundary. ORACLE FAILS by exactly one item across 40,300: an unposted EVENT_RESEARCH_OVERBUDGET - compare was blind because the event list was never a declared region. fpu_cw=0x127f => 53-bit double, x87 question SETTLED. No Zuul in the save: double roll still disassembly-only |
|
| P2-B3 ProcessResearch (behavioral, RNG) | phase2 | mapped | high | 85% | 2026-09-08 | LIVE, PARTIAL PASS: 15 calls compared, 13 zero-divergence; RNG post-state matched 14/15 incl. every roll (validates MT19937 + draw mapping + odds together). 2 divergences are the declared SetResearched boundary. ORACLE FAILS by exactly one item across 40,300: an unposted EVENT_RESEARCH_OVERBUDGET - compare was blind because the event list was never a declared region. fpu_cw=0x127f => 53-bit double, x87 question SETTLED. No Zuul in the save: double roll still disassembly-only |
|
||||||
| RNG signatures (Ghidra) | meta | verified | high | 100% | 2026-09-08 | Seed/Twist/NextFloat/NextInt verified; draw = y/(2^32-1); NextInt [0,n] inclusive; lazy twist; left@+0x9c4. RUNTIME CONFIRMED: fpu_cw=0x127f (53-bit double, round-nearest) - our next_float model is right, float_from_pc24 is an unused contingency |
|
| RNG signatures (Ghidra) | meta | verified | high | 100% | 2026-09-08 | Seed/Twist/NextFloat/NextInt verified; draw = y/(2^32-1); NextInt [0,n] inclusive; lazy twist; left@+0x9c4. RUNTIME CONFIRMED: fpu_cw=0x127f (53-bit double, round-nearest) - our next_float model is right, float_from_pc24 is an unused contingency |
|
||||||
| engine: game/effects | engine | verified | high | 100% | 2026-09-08 | merged: TechId enum (196 slots @10000+i), 44 ids with typed strategic effects, species flag bits, ApplyTechEffect; 254 checks |
|
| engine: game/effects | engine | verified | high | 100% | 2026-09-08 | merged: TechId enum (196 slots @10000+i), 44 ids with typed strategic effects, species flag bits, ApplyTechEffect; 254 checks |
|
||||||
| VM140 exclusivity (lab rule) | meta | verified | high | 100% | 2026-09-08 | one agent at a time. Holder: B4 (window open). QUEUE: empty. Windows Update now DISABLED/paused on the VM (was rebooting mid-run). Non-holders build /srv/re-lab/build/sots-engine-<lane>, stage dist-<lane>, deploy C:\SOTS\shimdist-<lane> |
|
| VM140 exclusivity (lab rule) | meta | verified | high | 100% | 2026-09-08 | one agent at a time. Holder: R-recapture (window open 2026-09-08). QUEUE: empty. Windows Update now DISABLED/paused on the VM (was rebooting mid-run). Non-holders build /srv/re-lab/build/sots-engine-<lane>, stage dist-<lane>, deploy C:\SOTS\shimdist-<lane> |
|
||||||
| Zuul double-roll (behavioural) | verify | backlog | — | 0% | 2026-09-08 | CONFIRMED NEEDED: ref-turn2 has only species 0 and 2, so the double roll is verified by disassembly + host tests only. Needs one compare from a species-5 save; the check is just that `left` drops by 2 not 1 |
|
| Zuul double-roll (behavioural) | verify | backlog | — | 0% | 2026-09-08 | CONFIRMED NEEDED: ref-turn2 has only species 0 and 2, so the double roll is verified by disassembly + host tests only. Needs one compare from a species-5 save; the check is just that `left` drops by 2 not 1 |
|
||||||
| budget tail coverage (expenses/aid/debt) | verify | backlog | — | 0% | 2026-09-08 | 8 ComputeBudget slots were always 0 in ref-turn2 (no sliders, no aid, no debt, no handicap). Need a save with expense sliders, a debtor and a research-aid treaty to exercise ExpenseTotal + the aid/bonus tail |
|
| budget tail coverage (expenses/aid/debt) | verify | backlog | — | 0% | 2026-09-08 | 8 ComputeBudget slots were always 0 in ref-turn2 (no sliders, no aid, no debt, no handicap). Need a save with expense sliders, a debtor and a research-aid treaty to exercise ExpenseTotal + the aid/bonus tail |
|
||||||
| hook GetDifficultyMods | meta | backlog | — | 0% | 2026-09-08 | B1 derived the two difficulty rows from trace values (AI maintenance divisor 3, research x1.5) instead of snapshotting them; hook it properly so they stop being constants |
|
| hook GetDifficultyMods | meta | backlog | — | 0% | 2026-09-08 | B1 derived the two difficulty rows from trace values (AI maintenance divisor 3, research x1.5) instead of snapshotting them; hook it properly so they stop being constants |
|
||||||
|
|
@ -66,5 +66,7 @@ Status flow: `backlog → in-progress → mapped → verified` (or `blocked`).
|
||||||
| P2-B4 colony + movement (behavioral) | phase2 | verified | high | 100% | 2026-09-08 | LIVE: 36 calls compared, 0 divergences, tracecmp exit 0. Scout's headline: RNG left-delta 0 and mt hash identical on ALL 28 systems (only ProcessRebellion draws; none fired) - fpu_cw 0x127f confirmed. One real fleet move reproduced bit-for-bit; PlanFleetMovement's schedule matched. 3 prototypes + 6 helpers VERIFIED and written back to Ghidra; 22 formula corrections. THREE hook bugs found by reading the trace, not the verdict (stale args from describe_args-before-regions; StrategyServer has TWO bases 4 bytes apart; off_Fleets was a Ghidra-base number used as raw) - each would have given a clean compare that checked nothing. COVERAGE IS THIN: only 3 owned systems, 1 moving fleet, gate traffic all-zero; bats2, plague, rebellion, slaves, terraform, jumps, arrivals untested. No replace mode (input boundary). VM released: main menu, hooks=trace, build b4-fix2-20260908T0615Z |
|
| P2-B4 colony + movement (behavioral) | phase2 | verified | high | 100% | 2026-09-08 | LIVE: 36 calls compared, 0 divergences, tracecmp exit 0. Scout's headline: RNG left-delta 0 and mt hash identical on ALL 28 systems (only ProcessRebellion draws; none fired) - fpu_cw 0x127f confirmed. One real fleet move reproduced bit-for-bit; PlanFleetMovement's schedule matched. 3 prototypes + 6 helpers VERIFIED and written back to Ghidra; 22 formula corrections. THREE hook bugs found by reading the trace, not the verdict (stale args from describe_args-before-regions; StrategyServer has TWO bases 4 bytes apart; off_Fleets was a Ghidra-base number used as raw) - each would have given a clean compare that checked nothing. COVERAGE IS THIN: only 3 owned systems, 1 moving fleet, gate traffic all-zero; bats2, plague, rebellion, slaves, terraform, jumps, arrivals untested. No replace mode (input boundary). VM released: main menu, hooks=trace, build b4-fix2-20260908T0615Z |
|
||||||
| harness gap: undeclared side-effect lists | verify | verified | high | 100% | 2026-09-08 | FIXED STRUCTURALLY (engine 3f0721f+): compile-time-required Coverage on every descriptor (a hook without one does not compile); Guard regions that catch AND localise undeclared writes (names player+0x2b0, not 'the hash moved'); replace mode now emits records; tracecmp prints coverage on every report + --strict-coverage. A hook claiming 'complete' while a guard caught an undeclared write now counts as a DIVERGENCE. Audit found 23 undeclared side effects: docs/harness-audit.md |
|
| harness gap: undeclared side-effect lists | verify | verified | high | 100% | 2026-09-08 | FIXED STRUCTURALLY (engine 3f0721f+): compile-time-required Coverage on every descriptor (a hook without one does not compile); Guard regions that catch AND localise undeclared writes (names player+0x2b0, not 'the hash moved'); replace mode now emits records; tracecmp prints coverage on every report + --strict-coverage. A hook claiming 'complete' while a guard caught an undeclared write now counts as a DIVERGENCE. Audit found 23 undeclared side effects: docs/harness-audit.md |
|
||||||
| RollResearchEvent draw (behavioural) | verify | backlog | — | 0% | 2026-09-08 | ServerPlayer::RollResearchEvent draws one NextFloat when the completing def is the current target and +0x3b4 is set. Region declared, ours reproduces it, but the branch never fired on ref-turn2 - needs a workload that sets research_roll_pending |
|
| RollResearchEvent draw (behavioural) | verify | backlog | — | 0% | 2026-09-08 | ServerPlayer::RollResearchEvent draws one NextFloat when the completing def is the current target and +0x3b4 is set. Region declared, ours reproduces it, but the branch never fired on ref-turn2 - needs a workload that sets research_roll_pending |
|
||||||
| golden-trace recapture (post-guards) | verify | backlog | — | 0% | 2026-09-08 | region sets changed, so goldens must be recaptured: ProcessResearch (expect NEW divergences - the event defect becoming visible), ComputeBudget (verdict should stay 0), and first captures for OnTechResearched / ServerSystem::ProcessTurn / MoveFleet |
|
| golden-trace recapture (post-guards) | verify | in-progress | — | 0% | 2026-09-08 | region sets changed, so goldens must be recaptured: ProcessResearch (expect NEW divergences - the event defect becoming visible), ComputeBudget (verdict should stay 0), and first captures for OnTechResearched / ServerSystem::ProcessTurn / MoveFleet |
|
||||||
| B1 replace double-run | verify | backlog | — | 0% | 2026-09-08 | ComputeBudget replace mode runs the original a second time to harvest budget slots; ComputeOutput repairs ships in orbit as a side effect, so this is a real per-turn double effect on objects no region covers. Needs a design fix (harvest without re-running, or declare+revert) |
|
| B1 replace double-run | verify | backlog | — | 0% | 2026-09-08 | ComputeBudget replace mode runs the original a second time to harvest budget slots; ComputeOutput repairs ships in orbit as a side effect, so this is a real per-turn double effect on objects no region covers. Needs a design fix (harvest without re-running, or declare+revert) |
|
||||||
|
| ReVa MCP link drop (workaround) | meta | verified | high | 100% | 2026-09-08 | The ReVa MCP client link dropped mid-session while the CT111 server stayed healthy (systemd active, :8080 listening, valid key -> 200). `tools/reva_call.py <tool> '<json>'` calls the same server over plain HTTP (initialize -> notifications/initialized -> tools/call; replies are SSE with a leading `id:` line, initialize is plain JSON). Key is NEVER stored in the repo: $REVA_KEY, else ~/.claude.json, else ssh to the CT properties file. Use this whenever mcp__plugin_ReVa_ReVa__* is unavailable |
|
||||||
|
| event posting API | subsystem | in-progress | — | 0% | 2026-09-08 | Closes B3's oracle gap (unposted EVENT_RESEARCH_OVERBUDGET, the ONE item wrong across 40,300) and B2's known gap (ours posts no events, so both clean compares bound economy fields only). Needs: the player event list container, the post/append entry point, the event record layout |
|
||||||
|
|
|
||||||
83
tools/reva_call.py
Executable file
83
tools/reva_call.py
Executable file
|
|
@ -0,0 +1,83 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Call a ReVa (Ghidra) MCP tool over plain HTTP.
|
||||||
|
|
||||||
|
Fallback for when the ReVa MCP client link drops but the server on CT111 is fine.
|
||||||
|
Usage:
|
||||||
|
tools/reva_call.py <tool-name> '<json-args>'
|
||||||
|
tools/reva_call.py --list
|
||||||
|
|
||||||
|
The API key is never stored here. It is read from, in order:
|
||||||
|
$REVA_KEY, then ~/.claude.json, then CT111's reva-lab.properties over ssh.
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
URL = os.environ.get("REVA_URL", "http://192.168.10.138:8080/mcp/message")
|
||||||
|
|
||||||
|
|
||||||
|
def api_key():
|
||||||
|
if os.environ.get("REVA_KEY"):
|
||||||
|
return os.environ["REVA_KEY"]
|
||||||
|
cfg = os.path.expanduser("~/.claude.json")
|
||||||
|
if os.path.exists(cfg):
|
||||||
|
m = re.search(r'"X-API-Key"\s*:\s*"([0-9a-f]{16,})"', open(cfg, encoding="utf-8").read())
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
out = subprocess.run(
|
||||||
|
["ssh", "spicy", "pct exec 111 -- grep '^reva.server.options.api.key=' /opt/reva-src/reva-lab.properties"],
|
||||||
|
capture_output=True, text=True, timeout=30)
|
||||||
|
m = re.search(r"api\.key=(\S+)", out.stdout)
|
||||||
|
if m:
|
||||||
|
return m.group(1)
|
||||||
|
sys.exit("no ReVa API key found (set $REVA_KEY)")
|
||||||
|
|
||||||
|
|
||||||
|
def rpc(key, method, params, session=None, notify=False):
|
||||||
|
msg = {"jsonrpc": "2.0", "method": method, "params": params}
|
||||||
|
if not notify:
|
||||||
|
msg["id"] = 1
|
||||||
|
req = urllib.request.Request(URL, data=json.dumps(msg).encode(), headers={
|
||||||
|
"X-API-Key": key,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
"Accept": "application/json, text/event-stream",
|
||||||
|
**({"Mcp-Session-Id": session} if session else {}),
|
||||||
|
})
|
||||||
|
with urllib.request.urlopen(req, timeout=300) as r:
|
||||||
|
sid = r.headers.get("Mcp-Session-Id") or session
|
||||||
|
raw = r.read().decode("utf-8", "replace").strip()
|
||||||
|
if not raw:
|
||||||
|
return {}, sid
|
||||||
|
# tools/* replies come back as SSE (id:/event:/data: lines); initialize is plain JSON.
|
||||||
|
if not raw.startswith("{"):
|
||||||
|
raw = "".join(ln[5:].strip() for ln in raw.splitlines() if ln.startswith("data:"))
|
||||||
|
return json.loads(raw), sid
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
sys.exit(__doc__)
|
||||||
|
key = api_key()
|
||||||
|
_, sid = rpc(key, "initialize", {
|
||||||
|
"protocolVersion": "2024-11-05", "capabilities": {},
|
||||||
|
"clientInfo": {"name": "reva_call", "version": "1"}})
|
||||||
|
rpc(key, "notifications/initialized", {}, sid, notify=True)
|
||||||
|
if sys.argv[1] == "--list":
|
||||||
|
res, _ = rpc(key, "tools/list", {}, sid)
|
||||||
|
for t in res.get("result", {}).get("tools", []):
|
||||||
|
print(f"{t['name']}: {t.get('description','')[:110]}")
|
||||||
|
return
|
||||||
|
args = json.loads(sys.argv[2]) if len(sys.argv) > 2 else {}
|
||||||
|
res, _ = rpc(key, "tools/call", {"name": sys.argv[1], "arguments": args}, sid)
|
||||||
|
if "error" in res:
|
||||||
|
print(json.dumps(res["error"], indent=2))
|
||||||
|
sys.exit(1)
|
||||||
|
for c in res.get("result", {}).get("content", []):
|
||||||
|
print(c.get("text", json.dumps(c)))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
Add table
Reference in a new issue