dashboard: count addresses.d fragments (was undercounting 615 vs 722), read layouts.json (22 -> 384), fix the layouts denominator and the 'objects' type row
This commit is contained in:
parent
e1f038e440
commit
648e9aae77
2 changed files with 34 additions and 21 deletions
|
|
@ -1,6 +1,6 @@
|
|||
# SotS RE campaign — coverage dashboard
|
||||
|
||||
Generated 2026-09-08 12:29 UTC · `sots-re` @ 136f98b,2026-09-08 · `sots-engine` @ c883a32,2026-09-08 (106 commits) · regenerate with `tools/dashboard.py`
|
||||
Generated 2026-09-08 12:30 UTC · `sots-re` @ e1f038e,2026-09-08 · `sots-engine` @ c883a32,2026-09-08 (106 commits) · regenerate with `tools/dashboard.py`
|
||||
|
||||
> **North star:** A functional reimplementation of the engine — behavior-equivalent, NOT byte-for-byte
|
||||
|
||||
|
|
@ -18,20 +18,19 @@ Generated 2026-09-08 12:29 UTC · `sots-re` @ 136f98b,2026-09-08 · `sots-engine
|
|||
|
||||
| Type | verified | mapped | in-progress | backlog | blocked | total |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| objects | 5 | 2 | 0 | 0 | 0 | 7 |
|
||||
| objects | 20 | 6 | 0 | 2 | 1 | 29 |
|
||||
| control-flow | 2 | 2 | 0 | 1 | 0 | 5 |
|
||||
| subsystems | 3 | 7 | 1 | 3 | 1 | 15 |
|
||||
| engine | 16 | 0 | 0 | 0 | 0 | 16 |
|
||||
| verify | 23 | 3 | 0 | 8 | 0 | 34 |
|
||||
| phase2 | 10 | 3 | 1 | 2 | 0 | 16 |
|
||||
| meta | 19 | 4 | 0 | 1 | 0 | 24 |
|
||||
| other | 15 | 4 | 0 | 2 | 1 | 22 |
|
||||
|
||||
## 2. Binary understanding
|
||||
|
||||
- RTTI type descriptors: **1,924** (`Game::` 1,404, `Mars::` 194; serializable types 179)
|
||||
- Classes with recovered member layouts: **22** / 179 serializable types `[█░░░░░░░░░] 12%` — heuristic: distinct `Game::X`/`Mars::X` in `##`–`####` headings of `struct-recovery.md` + `schema-gaps-resolved.md`
|
||||
- Functions: **41,411** (parsed from `01-fingerprint.md`); named/annotated in the **address contract** (`ghidra/addresses.json`, not Ghidra's full rename count): **615**, verified **607** `[██████████] 99%`
|
||||
- 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): **723**, verified **703** `[██████████] 97%`
|
||||
|
||||
## 3. Data layer
|
||||
|
||||
|
|
@ -96,10 +95,10 @@ Most recent open:
|
|||
|
||||
## 8. Delta since previous dashboard
|
||||
|
||||
- verified targets: 92 → 93 (+1) · mapped-or-better: 117 → 118 (+1)
|
||||
- verified targets: 93 → 93 (+0) · mapped-or-better: 118 → 118 (+0)
|
||||
- engine LOC: 35,208 → 35,208 (+0) · test files: 94 → 94 (+0) · checks: 3,142 → 3,142 (+0)
|
||||
- addresses verified: 607 → 607 (+0) · recovered layouts: 22 → 22 (+0) · open questions: 26 → 26 (+0)
|
||||
- addresses verified: 702 → 703 (+1) · recovered layouts: 384 → 384 (+0) · open questions: 26 → 26 (+0)
|
||||
|
||||
---
|
||||
warnings: board.md: unknown types objects; 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": 93, "mapped_plus": 118, "targets": 139, "loc": 35208, "tests": 94, "checks": 3142, "addr_verified": 607, "addr_total": 615, "layouts": 22, "open_q": 26} -->
|
||||
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": 93, "mapped_plus": 118, "targets": 139, "loc": 35208, "tests": 94, "checks": 3142, "addr_verified": 703, "addr_total": 723, "layouts": 384, "open_q": 26} -->
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ Parsing is tolerant: malformed inputs are reported in the footer "warnings" line
|
|||
"""
|
||||
import argparse
|
||||
import datetime
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
|
|
@ -22,7 +23,7 @@ WARN = []
|
|||
FUNCTIONS_FALLBACK = 41411 # findings/01-fingerprint.md, in case the number cannot be parsed
|
||||
STATUSES = ["verified", "mapped", "in-progress", "backlog", "blocked"]
|
||||
TYPE_ROWS = [ # (label, board Type values)
|
||||
("objects", ("object",)), ("control-flow", ("control-flow",)), ("subsystems", ("subsystem",)),
|
||||
("objects", ("object", "objects")), ("control-flow", ("control-flow",)), ("subsystems", ("subsystem",)),
|
||||
("engine", ("engine",)), ("verify", ("verify",)), ("phase2", ("phase2",)), ("meta", ("meta",)),
|
||||
]
|
||||
|
||||
|
|
@ -102,9 +103,17 @@ def parse_functions(path):
|
|||
|
||||
|
||||
def recovered_layouts(paths):
|
||||
"""Heuristic: unique `Game::X` / `Mars::X` names appearing in ##/###/#### headings of the
|
||||
struct-recovery docs, excluding purely descriptive headings (no backticked class)."""
|
||||
"""Classes with a recovered member layout.
|
||||
|
||||
Primary source is objects/layouts.json (the serializer-recovery output — machine-generated,
|
||||
hundreds of classes). The heading heuristic over the hand-written struct-recovery docs is kept
|
||||
as a supplement: it catches classes recovered by hand that the serializer pass never saw."""
|
||||
names = set()
|
||||
try:
|
||||
d = json.loads(read(rp("objects", "layouts.json")) or "{}")
|
||||
names.update(k for k in d if "::" in k)
|
||||
except json.JSONDecodeError as e:
|
||||
warn(f"layouts.json: {e}")
|
||||
for p in paths:
|
||||
for ln in read(p).splitlines():
|
||||
if re.match(r"^#{2,4} ", ln):
|
||||
|
|
@ -114,12 +123,16 @@ def recovered_layouts(paths):
|
|||
|
||||
|
||||
def parse_addresses(path):
|
||||
try:
|
||||
d = json.loads(read(path) or "{}")
|
||||
entries = d.get("entries", d if isinstance(d, list) else [])
|
||||
except json.JSONDecodeError as e:
|
||||
warn(f"addresses.json: {e}")
|
||||
entries = []
|
||||
# addresses.json plus every per-lane ghidra/addresses.d/*.json fragment — the same set
|
||||
# gen_addresses.py merges. Counting only the base file undercounts while lanes are in flight.
|
||||
sources = [path] + sorted(glob.glob(os.path.join(os.path.dirname(path), "addresses.d", "*.json")))
|
||||
entries = []
|
||||
for src in sources:
|
||||
try:
|
||||
d = json.loads(read(src) or "{}")
|
||||
entries += d.get("entries", d if isinstance(d, list) else [])
|
||||
except json.JSONDecodeError as e:
|
||||
warn(f"{os.path.basename(src)}: {e}")
|
||||
total = len(entries)
|
||||
verified = sum(1 for e in entries if str(e.get("status", "")).startswith("verified"))
|
||||
return total, verified
|
||||
|
|
@ -375,9 +388,10 @@ def render(engine, prev):
|
|||
a_total, a_ver = parse_addresses(rp("ghidra", "addresses.json"))
|
||||
L += ["## 2. Binary understanding", "",
|
||||
f"- RTTI type descriptors: **{n(rtti)}** (`Game::` {n(cg)}, `Mars::` {n(cm)}; serializable types {n(ser)})",
|
||||
f"- Classes with recovered member layouts: **{len(layouts)}** / {ser} serializable types "
|
||||
f"{bar(len(layouts), ser)} — heuristic: distinct `Game::X`/`Mars::X` in `##`–`####` headings of "
|
||||
f"`struct-recovery.md` + `schema-gaps-resolved.md`",
|
||||
f"- Classes with recovered member layouts: **{len(layouts)}** / {n(cg + cm)} named classes "
|
||||
f"{bar(len(layouts), cg + cm)} — `objects/layouts.json` (serializer recovery) plus classes "
|
||||
f"recovered by hand in `struct-recovery.md` + `schema-gaps-resolved.md`. Note {ser} types are "
|
||||
f"*serializable*; the recovery also reaches non-serializable ones, so this is not a subset of that",
|
||||
f"- Functions: **{n(funcs)}** ({fsrc} from `01-fingerprint.md`); named/annotated in the **address contract** "
|
||||
f"(`ghidra/addresses.json`, not Ghidra's full rename count): **{a_total}**, verified **{a_ver}** "
|
||||
f"{bar(a_ver, a_total)}", ""]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue