diff --git a/.github/workflows/progress.yml b/.github/workflows/progress.yml new file mode 100644 index 000000000..375eb9a72 --- /dev/null +++ b/.github/workflows/progress.yml @@ -0,0 +1,37 @@ +# .github/workflows/progress.yml — publish the progress report for decomp.dev (P33 D3). +# +# CI has no game disc, so it never rebuilds the game. The numbers come from the COMMITTED docs/progress.json, which +# `make report` regenerates from a local clean rebuild (and `make audit-digest` asserts describes the tree). This +# workflow converts that file to objdiff's report format (tools/objdiff_report.py, validated with objdiff-cli) and +# uploads it as the artifact decomp.dev reads: `_report` = SLUS_007.26_report. +name: progress + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: read + +jobs: + report: + name: objdiff report from docs/progress.json (no rebuild) + runs-on: ubuntu-24.04 + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + submodules: false + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - name: Convert the committed progress.json to an objdiff report + run: python tools/objdiff_report.py --in docs/progress.json --out report.json + - name: Print the headline + run: python -c "import json; m=json.load(open('report.json'))['measures']; print(f\"code {m['matched_code']}/{m['total_code']} = {m['matched_code_percent']:.2f}% functions {m['matched_functions']}/{m['total_functions']} units {m['complete_units']}/{m['total_units']}\")" + - uses: actions/upload-artifact@v4 + with: + name: SLUS_007.26_report + path: report.json + if-no-files-found: error diff --git a/Makefile b/Makefile index 2c70c9889..81a14a95e 100644 --- a/Makefile +++ b/Makefile @@ -228,6 +228,9 @@ audit-disc: # phantom. R34: the byte-gate is a null oracle for documents, so this is a second one that disagrees. audit-digest: $(VENV_PY) tools/audit_digest.py + # P33 D3: the published DATA must describe the current tree too — docs/progress.json, the README's + # generated block and the badge files (the same numbers as the digest; R51: never typed) + $(VENV_PY) tools/progress.py --json --readme --check # P30 S39 (Drew's MASTER_REMAINING proposal, derived form — docs/decision-log.md 2026-08-04): # "what's left" is answered by six artifacts, each individually derived and NONE ever checked diff --git a/docs/SETUP.md b/docs/SETUP.md index 0a36e658a..ef3b6655c 100644 --- a/docs/SETUP.md +++ b/docs/SETUP.md @@ -749,6 +749,9 @@ Every script under `tools/` (plus the two report make-targets), grouped by purpo | | `DefineFunctions.java` | Disassemble + create functions at splat's validated entry points (`.run/_funcs.txt`) — completes a raw-blob program's function set (Phase 10). | | | `ApplySymbols.java` + `tools/ghidra_apply_symbols.sh` | **(P31 S78) The Ghidra MIRROR of the curated symbol file (R15/G6), headless with a real save.** `tools/ghidra_apply_symbols.sh [PROG] [symbols files…]` (defaults `SLUS_007.26 config/symbols.us.txt`; MCP must be STOPPED first) reads `name = 0xADDR;` rows and sets every function/label to its curated name; a name held by another address is moved to that address's own curated name first (`firstfile`/`firstfile2`), else to `__at_`. Idempotent; prints `BFMAPPLY renamed_funcs=… unchanged=…`; R9-verify with `ghidra_mcp_verify.sh`. **Use this, not MCP `rename_symbol`/`batch_rename`, for renames:** S78 observed 47 MCP renames NOT persisting through the sentinel stop ("Save succeeded", DB grew, names gone — R9 caught it; cause not yet isolated), while the postScript path persisted 73/73 on the first run. | | **Public flip / CI** | `.github/workflows/no-rom.yml` | **(P33 B7) The ROM-free CI**: job `audits` (audit_public, audit_text_sources, verbatim_check --strict, cookbook_index --check, ghidra_roster --check, work_evidence --selftest, test_lzss, lint_symbol_refs — ≈45 s of checks) + job `compile-only` (binutils-mipsel + `cpp-mipsel-linux-gnu` from apt, cc1 from the tracked tarball sha256-checked, maspsx submodule; PR scope `main resident ov_SC01_077 md_MAIN_013`; `--all` weekly Mon 06:17 UTC + `workflow_dispatch`). Byte-identity is NOT proven in CI (needs the disc) — `docs/verification.md`. | +| **Publishing** | `tools/progress.py --json \| --readme [--check]` | **(P33 D1/D3)** The same numbers as DATA: `--json` → `docs/progress.json` (schema 1: the four metrics with numerator/denominator/pct, the counts, 218 per-binary rows incl. instruction totals; no run date) + `docs/badges/{fleet_instr,fleet_fn,distinct,binaries}.json` (shields endpoint format; the README references `fleet_instr` + `binaries` by name); `--readme` rewrites the README's `` block (refuses a README without the markers); `--check` asserts JSON + block + badges are fresh (in `make audit-digest`). Run by `make report BINARY=main`. | +| | `tools/objdiff_report.py [--in docs/progress.json] [--out report.json]` | **(P33 D3)** progress.json → objdiff's report format (report.proto v2, snake_case — validated with `objdiff-cli` 3.8.1 `report changes`): one unit per binary (code = instructions × 4, functions byte-identical / matchable, metadata complete), categories `game-code` and `linked-sony-objects` (functions only). `.github/workflows/progress.yml` runs it on every push (no rebuild — the committed JSON) and uploads the artifact **`SLUS_007.26_report`** for decomp.dev (Drew registers at decomp.dev/manage/new after the flip). | +| | `tools/frogress_upload.py [--push --project bfm --version us]` | **(P33 D3)** stdlib; `--dry-run` is the default (prints the payload); `--push` POSTs `{"api_key","entries":[{git_hash,timestamp,categories:{default:{measures…}}}]}` to `progress.deco.mp/data///` with `FROGRESS_API_SECRET` from the environment (never a file). frogress projects are admin-created — Drew requests the slug + key after the flip. | | | `tools/public_rewrite/` (P33 C1) | **The history-rewrite package** (`docs/public-flip-runbook.md` §3 is the operating table). `common.py` (shared: the purge rules, the DERIVED content-hash sets, identities from the log, the one hash regex, a persistent `cat-file --batch`) · `hash_dict.py [--write-mailmap]` (every commit OBJECT → `commit:NNNN` / twin / orphan; prefix index 7..40; asserts 0 ambiguous; records content-hash collisions as excluded; writes the scratch mailmap) · `scrub.py --test \| --sample \| --file` (THE scrub: hash tokens, addresses → noreply, trailer lines in messages; 12 known-true cases; the HEAD sample with git's own object lookup as the independent oracle) · `gate_scan.py --all\|--refs … [--worktree] [--expect-fail FIXTURE]` (paths ever touched × purge rules; every reachable blob's content sha1 × the ROM set; 5 byte signatures; 50 MiB; emits `rom_blob_ids.txt` = hits ∪ every blob ever under a purge path; the fixture `expected_offenders.txt` is the R39 negative control) · `run_filter.py [--sample]` (the git-filter-repo 2.47.0 module-API run inside the scratch bare clone; refuses elsewhere) · `verify_rewrite.py --old --new` (the pairwise proof) · `build_commit_map.py [--out]` (`docs/commit-map.tsv`, asserted free of old hashes) · `resolve_tokens.py [--check] [--map]` (tokens → shortest unique ≥9-char new abbreviations at the tip) · `absent_scan.py [--repo] [--tree]` (nothing old anywhere) · `probe_github.sh [--after-flip]` (Drew's purge probe). Scratch (`.run/public_rewrite/`, never committed): `dict.json`, `mailmap`, `rom_blob_ids.txt`, `old-to-new.tsv`, `repo.git`, the bundle. | | | `.venv/bin/git-filter-repo` 2.47.0 | (P33 C1) `pip install git-filter-repo==2.47.0` (in `requirements-python.txt`); used through its module API by `run_filter.py`. | | | `tools/audit_public.py [--paths …]` | **(P33 B7) The first-push gate**: no tracked file under `tools/public_rewrite/purge_set.txt` (the C1 rewrite's own input, filter-repo syntax), none whose SHA1 is ROM-derived (DERIVED set: every `sha1` in `extracted/retail/manifest.jsonl` + `config/check.*.sha` + the redump Track-1 SHA1; zero-length files exempt — the empty-file SHA1 is also SC04/SC05 `FILE_029/1.6`'s), none > 50 MiB. Names every offender, exits 1. ≈1 s over 6,798 paths. | @@ -1132,6 +1135,20 @@ fills fast). Nothing is leaking — but the host does not get the memory back on `tools/ghidra_*.sh` are repo-relative (`BFM_GHIDRA_PROJ` overrides the project dir; `ghidra_mcp_verify.sh [PROG]`); Makefile `GHIDRA_PROJ := $(or $(BFM_GHIDRA_PROJ),$(CURDIR)/ghidra)`. +### P33 D1–D3 (S87, 2026-09-07) — the README and the published numbers, generated never typed +- **D1 README:** rewritten from the Phase-19 text (every number was stale). Its numbers block is generated: `tools/progress.py + --json` writes `docs/progress.json` (every metric with its denominator, R41; no run date so `make report` never churns it) + and `--readme` rewrites the block between `` / ``; `--check` asserts both (and the + badges) are fresh and sits in `make audit-digest`; `make report BINARY=main` regenerates all of it after the fleet digest. +- **D2:** `LICENSE` (AGPL-3.0 verbatim from gnu.org, 661 lines), `src/NOTICE.md` (no license asserted over `src/`; never the + phrase "clean-room"), `THIRD_PARTY.md` (every license from the upstream LICENSE file or the GitHub API's license metadata: + old-gcc and ghidra_psx_ldr publish NONE — download-only rows), `tools/README.md` (the one AGPL statement). +- **D3:** badges (shields endpoint JSON, colour by percentage), `tools/objdiff_report.py` (validated: `objdiff-cli report + changes report.json report.json` parses and diffs it; a mutated unit shows as a change), `tools/frogress_upload.py` + (dry-run default), `.github/workflows/progress.yml` (artifact `SLUS_007.26_report`). CI never rebuilds the game: the report + is the committed `docs/progress.json` from a local clean rebuild. Outward actions after the flip (Drew): decomp.dev + registration, the frogress slug + key. The `objdiff-cli` binary used for validation lives in scratch (`.run/objdiff/`). + ### P33 C1 (S87, 2026-09-07) — the history-rewrite tooling, measured before the irreversible run - **Design points.** The scrub replaces a hex token only when the WHOLE token is a prefix (≥ 7) of an old commit hash — so a 16-char sig hash can never be mistaken for a commit; only 7–8-char tokens carry any false-positive risk (≈1.6e-5 diff --git a/docs/badges/binaries.json b/docs/badges/binaries.json new file mode 100644 index 000000000..700ff3269 --- /dev/null +++ b/docs/badges/binaries.json @@ -0,0 +1 @@ +{"schemaVersion": 1, "label": "byte-identical binaries", "message": "218/218", "color": "brightgreen"} diff --git a/docs/badges/distinct.json b/docs/badges/distinct.json new file mode 100644 index 000000000..5edb8fc55 --- /dev/null +++ b/docs/badges/distinct.json @@ -0,0 +1 @@ +{"schemaVersion": 1, "label": "distinct code matched", "message": "100.0%", "color": "brightgreen"} diff --git a/docs/badges/fleet_fn.json b/docs/badges/fleet_fn.json new file mode 100644 index 000000000..a691851e5 --- /dev/null +++ b/docs/badges/fleet_fn.json @@ -0,0 +1 @@ +{"schemaVersion": 1, "label": "matched (functions)", "message": "100.00%", "color": "brightgreen"} diff --git a/docs/badges/fleet_instr.json b/docs/badges/fleet_instr.json new file mode 100644 index 000000000..d1b5795f3 --- /dev/null +++ b/docs/badges/fleet_instr.json @@ -0,0 +1 @@ +{"schemaVersion": 1, "label": "matched (instructions)", "message": "100.0%", "color": "brightgreen"} diff --git a/docs/progress.json b/docs/progress.json index 4125fa48e..1cf0648af 100644 --- a/docs/progress.json +++ b/docs/progress.json @@ -48,7 +48,9 @@ "shared": 2, "linked": 1256, "byte_identical": 2091, - "matchable": 2091 + "matchable": 2091, + "instr_matched": 45150, + "instr_total": 45150 }, { "binary": "resident", @@ -56,7 +58,9 @@ "shared": 0, "linked": 0, "byte_identical": 145, - "matchable": 145 + "matchable": 145, + "instr_matched": 4483, + "instr_total": 4483 }, { "binary": "md_MAIN_001", @@ -64,7 +68,9 @@ "shared": 0, "linked": 0, "byte_identical": 11, - "matchable": 11 + "matchable": 11, + "instr_matched": 379, + "instr_total": 379 }, { "binary": "md_MAIN_003", @@ -72,7 +78,9 @@ "shared": 0, "linked": 0, "byte_identical": 64, - "matchable": 64 + "matchable": 64, + "instr_matched": 4520, + "instr_total": 4520 }, { "binary": "md_MAIN_007", @@ -80,7 +88,9 @@ "shared": 0, "linked": 0, "byte_identical": 19, - "matchable": 19 + "matchable": 19, + "instr_matched": 802, + "instr_total": 802 }, { "binary": "md_MAIN_008", @@ -88,7 +98,9 @@ "shared": 0, "linked": 0, "byte_identical": 6, - "matchable": 6 + "matchable": 6, + "instr_matched": 192, + "instr_total": 192 }, { "binary": "md_MAIN_009", @@ -96,7 +108,9 @@ "shared": 0, "linked": 0, "byte_identical": 12, - "matchable": 12 + "matchable": 12, + "instr_matched": 609, + "instr_total": 609 }, { "binary": "md_MAIN_011", @@ -104,7 +118,9 @@ "shared": 0, "linked": 0, "byte_identical": 21, - "matchable": 21 + "matchable": 21, + "instr_matched": 4321, + "instr_total": 4321 }, { "binary": "md_MAIN_013", @@ -112,7 +128,9 @@ "shared": 0, "linked": 0, "byte_identical": 16, - "matchable": 16 + "matchable": 16, + "instr_matched": 649, + "instr_total": 649 }, { "binary": "md_MAIN_014", @@ -120,7 +138,9 @@ "shared": 0, "linked": 0, "byte_identical": 13, - "matchable": 13 + "matchable": 13, + "instr_matched": 492, + "instr_total": 492 }, { "binary": "md_MAIN_015", @@ -128,7 +148,9 @@ "shared": 1, "linked": 0, "byte_identical": 20, - "matchable": 20 + "matchable": 20, + "instr_matched": 813, + "instr_total": 813 }, { "binary": "md_MAIN_016", @@ -136,7 +158,9 @@ "shared": 0, "linked": 0, "byte_identical": 12, - "matchable": 12 + "matchable": 12, + "instr_matched": 452, + "instr_total": 452 }, { "binary": "md_MAIN_017", @@ -144,7 +168,9 @@ "shared": 0, "linked": 0, "byte_identical": 10, - "matchable": 10 + "matchable": 10, + "instr_matched": 323, + "instr_total": 323 }, { "binary": "md_MAIN_018", @@ -152,7 +178,9 @@ "shared": 0, "linked": 0, "byte_identical": 11, - "matchable": 11 + "matchable": 11, + "instr_matched": 503, + "instr_total": 503 }, { "binary": "md_MAIN_019", @@ -160,7 +188,9 @@ "shared": 0, "linked": 0, "byte_identical": 22, - "matchable": 22 + "matchable": 22, + "instr_matched": 1128, + "instr_total": 1128 }, { "binary": "md_MAIN_020", @@ -168,7 +198,9 @@ "shared": 0, "linked": 0, "byte_identical": 14, - "matchable": 14 + "matchable": 14, + "instr_matched": 250, + "instr_total": 250 }, { "binary": "md_MAIN_021", @@ -176,7 +208,9 @@ "shared": 0, "linked": 0, "byte_identical": 11, - "matchable": 11 + "matchable": 11, + "instr_matched": 444, + "instr_total": 444 }, { "binary": "md_MAIN_022", @@ -184,7 +218,9 @@ "shared": 0, "linked": 0, "byte_identical": 33, - "matchable": 33 + "matchable": 33, + "instr_matched": 929, + "instr_total": 929 }, { "binary": "md_MAIN_023", @@ -192,7 +228,9 @@ "shared": 1, "linked": 0, "byte_identical": 6, - "matchable": 6 + "matchable": 6, + "instr_matched": 77, + "instr_total": 77 }, { "binary": "md_MAIN_024", @@ -200,7 +238,9 @@ "shared": 0, "linked": 0, "byte_identical": 6, - "matchable": 6 + "matchable": 6, + "instr_matched": 63, + "instr_total": 63 }, { "binary": "md_MAIN_025", @@ -208,7 +248,9 @@ "shared": 0, "linked": 0, "byte_identical": 30, - "matchable": 30 + "matchable": 30, + "instr_matched": 924, + "instr_total": 924 }, { "binary": "md_MAIN_026", @@ -216,7 +258,9 @@ "shared": 0, "linked": 0, "byte_identical": 24, - "matchable": 24 + "matchable": 24, + "instr_matched": 833, + "instr_total": 833 }, { "binary": "md_MAIN_027", @@ -224,7 +268,9 @@ "shared": 0, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 1226, + "instr_total": 1226 }, { "binary": "md_MAIN_028", @@ -232,7 +278,9 @@ "shared": 0, "linked": 0, "byte_identical": 22, - "matchable": 22 + "matchable": 22, + "instr_matched": 1058, + "instr_total": 1058 }, { "binary": "md_MAIN_029", @@ -240,7 +288,9 @@ "shared": 0, "linked": 0, "byte_identical": 11, - "matchable": 11 + "matchable": 11, + "instr_matched": 420, + "instr_total": 420 }, { "binary": "md_MAIN_030", @@ -248,7 +298,9 @@ "shared": 0, "linked": 0, "byte_identical": 10, - "matchable": 10 + "matchable": 10, + "instr_matched": 403, + "instr_total": 403 }, { "binary": "md_MAIN_031", @@ -256,7 +308,9 @@ "shared": 0, "linked": 0, "byte_identical": 18, - "matchable": 18 + "matchable": 18, + "instr_matched": 1100, + "instr_total": 1100 }, { "binary": "md_MAIN_032", @@ -264,7 +318,9 @@ "shared": 1, "linked": 0, "byte_identical": 10, - "matchable": 10 + "matchable": 10, + "instr_matched": 280, + "instr_total": 280 }, { "binary": "md_MAIN_033", @@ -272,7 +328,9 @@ "shared": 0, "linked": 0, "byte_identical": 19, - "matchable": 19 + "matchable": 19, + "instr_matched": 659, + "instr_total": 659 }, { "binary": "md_MAIN_034", @@ -280,7 +338,9 @@ "shared": 0, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 1752, + "instr_total": 1752 }, { "binary": "md_MAIN_035", @@ -288,7 +348,9 @@ "shared": 0, "linked": 0, "byte_identical": 16, - "matchable": 16 + "matchable": 16, + "instr_matched": 283, + "instr_total": 283 }, { "binary": "md_MAIN_036", @@ -296,7 +358,9 @@ "shared": 0, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 1122, + "instr_total": 1122 }, { "binary": "md_MAIN_037", @@ -304,7 +368,9 @@ "shared": 0, "linked": 0, "byte_identical": 17, - "matchable": 17 + "matchable": 17, + "instr_matched": 498, + "instr_total": 498 }, { "binary": "md_MAIN_038", @@ -312,7 +378,9 @@ "shared": 0, "linked": 0, "byte_identical": 20, - "matchable": 20 + "matchable": 20, + "instr_matched": 846, + "instr_total": 846 }, { "binary": "md_MAIN_039", @@ -320,7 +388,9 @@ "shared": 0, "linked": 0, "byte_identical": 26, - "matchable": 26 + "matchable": 26, + "instr_matched": 1032, + "instr_total": 1032 }, { "binary": "md_MAIN_040", @@ -328,7 +398,9 @@ "shared": 0, "linked": 0, "byte_identical": 19, - "matchable": 19 + "matchable": 19, + "instr_matched": 687, + "instr_total": 687 }, { "binary": "md_MAIN_041", @@ -336,7 +408,9 @@ "shared": 1, "linked": 0, "byte_identical": 15, - "matchable": 15 + "matchable": 15, + "instr_matched": 626, + "instr_total": 626 }, { "binary": "md_MAIN_042", @@ -344,7 +418,9 @@ "shared": 0, "linked": 0, "byte_identical": 4, - "matchable": 4 + "matchable": 4, + "instr_matched": 157, + "instr_total": 157 }, { "binary": "md_MAIN_043", @@ -352,7 +428,9 @@ "shared": 0, "linked": 0, "byte_identical": 23, - "matchable": 23 + "matchable": 23, + "instr_matched": 751, + "instr_total": 751 }, { "binary": "md_MAIN_044", @@ -360,7 +438,9 @@ "shared": 0, "linked": 0, "byte_identical": 43, - "matchable": 43 + "matchable": 43, + "instr_matched": 1457, + "instr_total": 1457 }, { "binary": "md_MAIN_045", @@ -368,7 +448,9 @@ "shared": 0, "linked": 0, "byte_identical": 21, - "matchable": 21 + "matchable": 21, + "instr_matched": 722, + "instr_total": 722 }, { "binary": "md_MAIN_046", @@ -376,7 +458,9 @@ "shared": 0, "linked": 0, "byte_identical": 39, - "matchable": 39 + "matchable": 39, + "instr_matched": 1340, + "instr_total": 1340 }, { "binary": "md_MAIN_047", @@ -384,7 +468,9 @@ "shared": 0, "linked": 0, "byte_identical": 12, - "matchable": 12 + "matchable": 12, + "instr_matched": 746, + "instr_total": 746 }, { "binary": "md_SC02_009", @@ -392,7 +478,9 @@ "shared": 0, "linked": 0, "byte_identical": 40, - "matchable": 40 + "matchable": 40, + "instr_matched": 1108, + "instr_total": 1108 }, { "binary": "md_SC03_053", @@ -400,7 +488,9 @@ "shared": 0, "linked": 0, "byte_identical": 15, - "matchable": 15 + "matchable": 15, + "instr_matched": 372, + "instr_total": 372 }, { "binary": "md_SC03_054", @@ -408,7 +498,9 @@ "shared": 0, "linked": 0, "byte_identical": 7, - "matchable": 7 + "matchable": 7, + "instr_matched": 764, + "instr_total": 764 }, { "binary": "md_SC03_056", @@ -416,7 +508,9 @@ "shared": 0, "linked": 0, "byte_identical": 4, - "matchable": 4 + "matchable": 4, + "instr_matched": 61, + "instr_total": 61 }, { "binary": "md_SC03_073", @@ -424,7 +518,9 @@ "shared": 10, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 645, + "instr_total": 645 }, { "binary": "md_SC03_074", @@ -432,7 +528,9 @@ "shared": 10, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 687, + "instr_total": 687 }, { "binary": "md_SC03_075", @@ -440,7 +538,9 @@ "shared": 10, "linked": 0, "byte_identical": 41, - "matchable": 41 + "matchable": 41, + "instr_matched": 993, + "instr_total": 993 }, { "binary": "md_SC03_076", @@ -448,7 +548,9 @@ "shared": 0, "linked": 0, "byte_identical": 66, - "matchable": 66 + "matchable": 66, + "instr_matched": 3276, + "instr_total": 3276 }, { "binary": "md_SC03_077", @@ -456,7 +558,9 @@ "shared": 0, "linked": 0, "byte_identical": 35, - "matchable": 35 + "matchable": 35, + "instr_matched": 767, + "instr_total": 767 }, { "binary": "md_SC03_078", @@ -464,7 +568,9 @@ "shared": 9, "linked": 0, "byte_identical": 27, - "matchable": 27 + "matchable": 27, + "instr_matched": 601, + "instr_total": 601 }, { "binary": "md_SC03_079", @@ -472,7 +578,9 @@ "shared": 0, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 670, + "instr_total": 670 }, { "binary": "md_SC03_132", @@ -480,7 +588,9 @@ "shared": 0, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 639, + "instr_total": 639 }, { "binary": "md_SC03_133", @@ -488,7 +598,9 @@ "shared": 1, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 681, + "instr_total": 681 }, { "binary": "md_SC03_134", @@ -496,7 +608,9 @@ "shared": 1, "linked": 0, "byte_identical": 41, - "matchable": 41 + "matchable": 41, + "instr_matched": 987, + "instr_total": 987 }, { "binary": "md_SC03_135", @@ -504,7 +618,9 @@ "shared": 0, "linked": 0, "byte_identical": 66, - "matchable": 66 + "matchable": 66, + "instr_matched": 3270, + "instr_total": 3270 }, { "binary": "md_SC03_136", @@ -512,7 +628,9 @@ "shared": 0, "linked": 0, "byte_identical": 35, - "matchable": 35 + "matchable": 35, + "instr_matched": 753, + "instr_total": 753 }, { "binary": "md_SC03_137", @@ -520,7 +638,9 @@ "shared": 1, "linked": 0, "byte_identical": 27, - "matchable": 27 + "matchable": 27, + "instr_matched": 595, + "instr_total": 595 }, { "binary": "md_SC03_138", @@ -528,7 +648,9 @@ "shared": 1, "linked": 0, "byte_identical": 37, - "matchable": 37 + "matchable": 37, + "instr_matched": 829, + "instr_total": 829 }, { "binary": "md_SC04_024", @@ -536,7 +658,9 @@ "shared": 0, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 649, + "instr_total": 649 }, { "binary": "md_SC04_025", @@ -544,7 +668,9 @@ "shared": 0, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 691, + "instr_total": 691 }, { "binary": "md_SC04_026", @@ -552,7 +678,9 @@ "shared": 0, "linked": 0, "byte_identical": 41, - "matchable": 41 + "matchable": 41, + "instr_matched": 997, + "instr_total": 997 }, { "binary": "md_SC04_027", @@ -560,7 +688,9 @@ "shared": 0, "linked": 0, "byte_identical": 66, - "matchable": 66 + "matchable": 66, + "instr_matched": 3280, + "instr_total": 3280 }, { "binary": "md_SC04_028", @@ -568,7 +698,9 @@ "shared": 0, "linked": 0, "byte_identical": 35, - "matchable": 35 + "matchable": 35, + "instr_matched": 763, + "instr_total": 763 }, { "binary": "md_SC04_029", @@ -576,7 +708,9 @@ "shared": 0, "linked": 0, "byte_identical": 27, - "matchable": 27 + "matchable": 27, + "instr_matched": 605, + "instr_total": 605 }, { "binary": "md_SC04_030", @@ -584,7 +718,9 @@ "shared": 0, "linked": 0, "byte_identical": 31, - "matchable": 31 + "matchable": 31, + "instr_matched": 678, + "instr_total": 678 }, { "binary": "md_SC05_023", @@ -592,7 +728,9 @@ "shared": 0, "linked": 0, "byte_identical": 28, - "matchable": 28 + "matchable": 28, + "instr_matched": 659, + "instr_total": 659 }, { "binary": "md_SC05_024", @@ -600,7 +738,9 @@ "shared": 0, "linked": 0, "byte_identical": 29, - "matchable": 29 + "matchable": 29, + "instr_matched": 701, + "instr_total": 701 }, { "binary": "md_SC05_025", @@ -608,7 +748,9 @@ "shared": 0, "linked": 0, "byte_identical": 41, - "matchable": 41 + "matchable": 41, + "instr_matched": 1007, + "instr_total": 1007 }, { "binary": "md_SC05_026", @@ -616,7 +758,9 @@ "shared": 0, "linked": 0, "byte_identical": 66, - "matchable": 66 + "matchable": 66, + "instr_matched": 3290, + "instr_total": 3290 }, { "binary": "md_SC05_027", @@ -624,7 +768,9 @@ "shared": 0, "linked": 0, "byte_identical": 35, - "matchable": 35 + "matchable": 35, + "instr_matched": 773, + "instr_total": 773 }, { "binary": "md_SC05_028", @@ -632,7 +778,9 @@ "shared": 0, "linked": 0, "byte_identical": 27, - "matchable": 27 + "matchable": 27, + "instr_matched": 615, + "instr_total": 615 }, { "binary": "md_SC05_029", @@ -640,7 +788,9 @@ "shared": 0, "linked": 0, "byte_identical": 31, - "matchable": 31 + "matchable": 31, + "instr_matched": 688, + "instr_total": 688 }, { "binary": "md_SC07_003", @@ -648,7 +798,9 @@ "shared": 0, "linked": 0, "byte_identical": 100, - "matchable": 100 + "matchable": 100, + "instr_matched": 6266, + "instr_total": 6266 }, { "binary": "md_SC07_004", @@ -656,7 +808,9 @@ "shared": 0, "linked": 0, "byte_identical": 315, - "matchable": 315 + "matchable": 315, + "instr_matched": 15888, + "instr_total": 15888 }, { "binary": "ov_MAIN_012", @@ -664,7 +818,9 @@ "shared": 1693, "linked": 0, "byte_identical": 2401, - "matchable": 2401 + "matchable": 2401, + "instr_matched": 88184, + "instr_total": 88184 }, { "binary": "ov_SC01_000", @@ -672,7 +828,9 @@ "shared": 1814, "linked": 0, "byte_identical": 2403, - "matchable": 2403 + "matchable": 2403, + "instr_matched": 88729, + "instr_total": 88729 }, { "binary": "ov_SC01_001", @@ -680,7 +838,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2466, - "matchable": 2466 + "matchable": 2466, + "instr_matched": 93613, + "instr_total": 93613 }, { "binary": "ov_SC01_004", @@ -688,7 +848,9 @@ "shared": 1807, "linked": 0, "byte_identical": 2414, - "matchable": 2414 + "matchable": 2414, + "instr_matched": 89118, + "instr_total": 89118 }, { "binary": "ov_SC01_005", @@ -696,7 +858,9 @@ "shared": 1838, "linked": 0, "byte_identical": 2503, - "matchable": 2503 + "matchable": 2503, + "instr_matched": 92291, + "instr_total": 92291 }, { "binary": "ov_SC01_006", @@ -704,7 +868,9 @@ "shared": 1838, "linked": 0, "byte_identical": 2503, - "matchable": 2503 + "matchable": 2503, + "instr_matched": 92291, + "instr_total": 92291 }, { "binary": "ov_SC01_008", @@ -712,7 +878,9 @@ "shared": 1808, "linked": 0, "byte_identical": 2426, - "matchable": 2426 + "matchable": 2426, + "instr_matched": 89467, + "instr_total": 89467 }, { "binary": "ov_SC01_009", @@ -720,7 +888,9 @@ "shared": 1808, "linked": 0, "byte_identical": 2507, - "matchable": 2507 + "matchable": 2507, + "instr_matched": 92661, + "instr_total": 92661 }, { "binary": "ov_SC01_074", @@ -728,7 +898,9 @@ "shared": 1808, "linked": 0, "byte_identical": 2426, - "matchable": 2426 + "matchable": 2426, + "instr_matched": 88341, + "instr_total": 88341 }, { "binary": "ov_SC01_077", @@ -736,7 +908,9 @@ "shared": 1769, "linked": 0, "byte_identical": 2586, - "matchable": 2586 + "matchable": 2586, + "instr_matched": 96862, + "instr_total": 96862 }, { "binary": "ov_SC01_080", @@ -744,7 +918,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2512, - "matchable": 2512 + "matchable": 2512, + "instr_matched": 93421, + "instr_total": 93421 }, { "binary": "ov_SC01_084", @@ -752,7 +928,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2579, - "matchable": 2579 + "matchable": 2579, + "instr_matched": 96682, + "instr_total": 96682 }, { "binary": "ov_SC02_000", @@ -760,7 +938,9 @@ "shared": 1902, "linked": 0, "byte_identical": 2683, - "matchable": 2683 + "matchable": 2683, + "instr_matched": 101014, + "instr_total": 101014 }, { "binary": "ov_SC02_003", @@ -768,7 +948,9 @@ "shared": 1902, "linked": 0, "byte_identical": 2683, - "matchable": 2683 + "matchable": 2683, + "instr_matched": 101014, + "instr_total": 101014 }, { "binary": "ov_SC02_004", @@ -776,7 +958,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2401, - "matchable": 2401 + "matchable": 2401, + "instr_matched": 87758, + "instr_total": 87758 }, { "binary": "ov_SC02_005", @@ -784,7 +968,9 @@ "shared": 1807, "linked": 0, "byte_identical": 2926, - "matchable": 2926 + "matchable": 2926, + "instr_matched": 106959, + "instr_total": 106959 }, { "binary": "ov_SC02_011", @@ -792,7 +978,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2893, - "matchable": 2893 + "matchable": 2893, + "instr_matched": 107235, + "instr_total": 107235 }, { "binary": "ov_SC02_015", @@ -800,7 +988,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2414, - "matchable": 2414 + "matchable": 2414, + "instr_matched": 88104, + "instr_total": 88104 }, { "binary": "ov_SC02_016", @@ -808,7 +998,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2545, - "matchable": 2545 + "matchable": 2545, + "instr_matched": 94390, + "instr_total": 94390 }, { "binary": "ov_SC02_017", @@ -816,7 +1008,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2732, - "matchable": 2732 + "matchable": 2732, + "instr_matched": 100556, + "instr_total": 100556 }, { "binary": "ov_SC02_021", @@ -824,7 +1018,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2437, - "matchable": 2437 + "matchable": 2437, + "instr_matched": 89673, + "instr_total": 89673 }, { "binary": "ov_SC02_026", @@ -832,7 +1028,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2572, - "matchable": 2572 + "matchable": 2572, + "instr_matched": 96222, + "instr_total": 96222 }, { "binary": "ov_SC02_027", @@ -840,7 +1038,9 @@ "shared": 1833, "linked": 0, "byte_identical": 2692, - "matchable": 2692 + "matchable": 2692, + "instr_matched": 101415, + "instr_total": 101415 }, { "binary": "ov_SC02_028", @@ -848,7 +1048,9 @@ "shared": 1832, "linked": 0, "byte_identical": 2701, - "matchable": 2701 + "matchable": 2701, + "instr_matched": 101544, + "instr_total": 101544 }, { "binary": "ov_SC02_031", @@ -856,7 +1058,9 @@ "shared": 1814, "linked": 0, "byte_identical": 2562, - "matchable": 2562 + "matchable": 2562, + "instr_matched": 94899, + "instr_total": 94899 }, { "binary": "ov_SC02_035", @@ -864,7 +1068,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2520, - "matchable": 2520 + "matchable": 2520, + "instr_matched": 94411, + "instr_total": 94411 }, { "binary": "ov_SC02_037", @@ -872,7 +1078,9 @@ "shared": 1708, "linked": 0, "byte_identical": 2515, - "matchable": 2515 + "matchable": 2515, + "instr_matched": 93850, + "instr_total": 93850 }, { "binary": "ov_SC02_039", @@ -880,7 +1088,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2416, - "matchable": 2416 + "matchable": 2416, + "instr_matched": 89046, + "instr_total": 89046 }, { "binary": "ov_SC02_041", @@ -888,7 +1098,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2561, - "matchable": 2561 + "matchable": 2561, + "instr_matched": 94986, + "instr_total": 94986 }, { "binary": "ov_SC03_001", @@ -896,7 +1108,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2869, - "matchable": 2869 + "matchable": 2869, + "instr_matched": 103474, + "instr_total": 103474 }, { "binary": "ov_SC03_002", @@ -904,7 +1118,9 @@ "shared": 1820, "linked": 0, "byte_identical": 2631, - "matchable": 2631 + "matchable": 2631, + "instr_matched": 95446, + "instr_total": 95446 }, { "binary": "ov_SC03_003", @@ -912,7 +1128,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2423, - "matchable": 2423 + "matchable": 2423, + "instr_matched": 89160, + "instr_total": 89160 }, { "binary": "ov_SC03_006", @@ -920,7 +1138,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2767, - "matchable": 2767 + "matchable": 2767, + "instr_matched": 102671, + "instr_total": 102671 }, { "binary": "ov_SC03_007", @@ -928,7 +1148,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2623, - "matchable": 2623 + "matchable": 2623, + "instr_matched": 97421, + "instr_total": 97421 }, { "binary": "ov_SC03_010", @@ -936,7 +1158,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2471, - "matchable": 2471 + "matchable": 2471, + "instr_matched": 89941, + "instr_total": 89941 }, { "binary": "ov_SC03_011", @@ -944,7 +1168,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2527, - "matchable": 2527 + "matchable": 2527, + "instr_matched": 91185, + "instr_total": 91185 }, { "binary": "ov_SC03_012", @@ -952,7 +1178,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2406, - "matchable": 2406 + "matchable": 2406, + "instr_matched": 88041, + "instr_total": 88041 }, { "binary": "ov_SC03_013", @@ -960,7 +1188,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2493, - "matchable": 2493 + "matchable": 2493, + "instr_matched": 90979, + "instr_total": 90979 }, { "binary": "ov_SC03_014", @@ -968,7 +1198,9 @@ "shared": 1879, "linked": 0, "byte_identical": 2685, - "matchable": 2685 + "matchable": 2685, + "instr_matched": 101618, + "instr_total": 101618 }, { "binary": "ov_SC03_015", @@ -976,7 +1208,9 @@ "shared": 1879, "linked": 0, "byte_identical": 2468, - "matchable": 2468 + "matchable": 2468, + "instr_matched": 101618, + "instr_total": 101618 }, { "binary": "ov_SC03_023", @@ -984,7 +1218,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2435, - "matchable": 2435 + "matchable": 2435, + "instr_matched": 88913, + "instr_total": 88913 }, { "binary": "ov_SC03_024", @@ -992,7 +1228,9 @@ "shared": 1837, "linked": 0, "byte_identical": 2641, - "matchable": 2641 + "matchable": 2641, + "instr_matched": 97114, + "instr_total": 97114 }, { "binary": "ov_SC03_028", @@ -1000,7 +1238,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2664, - "matchable": 2664 + "matchable": 2664, + "instr_matched": 101901, + "instr_total": 101901 }, { "binary": "ov_SC03_029", @@ -1008,7 +1248,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2644, - "matchable": 2644 + "matchable": 2644, + "instr_matched": 97691, + "instr_total": 97691 }, { "binary": "ov_SC03_030", @@ -1016,7 +1258,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2495, - "matchable": 2495 + "matchable": 2495, + "instr_matched": 91946, + "instr_total": 91946 }, { "binary": "ov_SC03_031", @@ -1024,7 +1268,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2514, - "matchable": 2514 + "matchable": 2514, + "instr_matched": 92273, + "instr_total": 92273 }, { "binary": "ov_SC03_089", @@ -1032,7 +1278,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2581, - "matchable": 2581 + "matchable": 2581, + "instr_matched": 99632, + "instr_total": 99632 }, { "binary": "ov_SC03_090", @@ -1040,7 +1288,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2625, - "matchable": 2625 + "matchable": 2625, + "instr_matched": 101945, + "instr_total": 101945 }, { "binary": "ov_SC03_091", @@ -1048,7 +1298,9 @@ "shared": 1833, "linked": 0, "byte_identical": 2640, - "matchable": 2640 + "matchable": 2640, + "instr_matched": 102883, + "instr_total": 102883 }, { "binary": "ov_SC03_092", @@ -1056,7 +1308,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2588, - "matchable": 2588 + "matchable": 2588, + "instr_matched": 94935, + "instr_total": 94935 }, { "binary": "ov_SC03_093", @@ -1064,7 +1318,9 @@ "shared": 1834, "linked": 0, "byte_identical": 2563, - "matchable": 2563 + "matchable": 2563, + "instr_matched": 96077, + "instr_total": 96077 }, { "binary": "ov_SC03_094", @@ -1072,7 +1328,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2577, - "matchable": 2577 + "matchable": 2577, + "instr_matched": 97740, + "instr_total": 97740 }, { "binary": "ov_SC03_095", @@ -1080,7 +1338,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2474, - "matchable": 2474 + "matchable": 2474, + "instr_matched": 90980, + "instr_total": 90980 }, { "binary": "ov_SC03_096", @@ -1088,7 +1348,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2465, - "matchable": 2465 + "matchable": 2465, + "instr_matched": 90692, + "instr_total": 90692 }, { "binary": "ov_SC03_097", @@ -1096,7 +1358,9 @@ "shared": 1832, "linked": 0, "byte_identical": 2603, - "matchable": 2603 + "matchable": 2603, + "instr_matched": 96060, + "instr_total": 96060 }, { "binary": "ov_SC03_098", @@ -1104,7 +1368,9 @@ "shared": 1833, "linked": 0, "byte_identical": 2541, - "matchable": 2541 + "matchable": 2541, + "instr_matched": 95327, + "instr_total": 95327 }, { "binary": "ov_SC03_099", @@ -1112,7 +1378,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2504, - "matchable": 2504 + "matchable": 2504, + "instr_matched": 93343, + "instr_total": 93343 }, { "binary": "ov_SC03_100", @@ -1120,7 +1388,9 @@ "shared": 1833, "linked": 0, "byte_identical": 2539, - "matchable": 2539 + "matchable": 2539, + "instr_matched": 94674, + "instr_total": 94674 }, { "binary": "ov_SC03_101", @@ -1128,7 +1398,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2528, - "matchable": 2528 + "matchable": 2528, + "instr_matched": 93641, + "instr_total": 93641 }, { "binary": "ov_SC03_102", @@ -1136,7 +1408,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2492, - "matchable": 2492 + "matchable": 2492, + "instr_matched": 96247, + "instr_total": 96247 }, { "binary": "ov_SC03_103", @@ -1144,7 +1418,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2510, - "matchable": 2510 + "matchable": 2510, + "instr_matched": 94179, + "instr_total": 94179 }, { "binary": "ov_SC03_104", @@ -1152,7 +1428,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2616, - "matchable": 2616 + "matchable": 2616, + "instr_matched": 101063, + "instr_total": 101063 }, { "binary": "ov_SC03_105", @@ -1160,7 +1438,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2597, - "matchable": 2597 + "matchable": 2597, + "instr_matched": 100457, + "instr_total": 100457 }, { "binary": "ov_SC03_107", @@ -1168,7 +1448,9 @@ "shared": 1693, "linked": 0, "byte_identical": 2496, - "matchable": 2496 + "matchable": 2496, + "instr_matched": 92353, + "instr_total": 92353 }, { "binary": "ov_SC03_108", @@ -1176,7 +1458,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2443, - "matchable": 2443 + "matchable": 2443, + "instr_matched": 90815, + "instr_total": 90815 }, { "binary": "ov_SC03_109", @@ -1184,7 +1468,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2424, - "matchable": 2424 + "matchable": 2424, + "instr_matched": 88170, + "instr_total": 88170 }, { "binary": "ov_SC03_110", @@ -1192,7 +1478,9 @@ "shared": 1835, "linked": 0, "byte_identical": 2468, - "matchable": 2468 + "matchable": 2468, + "instr_matched": 91890, + "instr_total": 91890 }, { "binary": "ov_SC03_111", @@ -1200,7 +1488,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2510, - "matchable": 2510 + "matchable": 2510, + "instr_matched": 94687, + "instr_total": 94687 }, { "binary": "ov_SC03_112", @@ -1208,7 +1498,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2526, - "matchable": 2526 + "matchable": 2526, + "instr_matched": 95585, + "instr_total": 95585 }, { "binary": "ov_SC03_113", @@ -1216,7 +1508,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2468, - "matchable": 2468 + "matchable": 2468, + "instr_matched": 92941, + "instr_total": 92941 }, { "binary": "ov_SC03_114", @@ -1224,7 +1518,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2415, - "matchable": 2415 + "matchable": 2415, + "instr_matched": 88615, + "instr_total": 88615 }, { "binary": "ov_SC03_115", @@ -1232,7 +1528,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2472, - "matchable": 2472 + "matchable": 2472, + "instr_matched": 90306, + "instr_total": 90306 }, { "binary": "ov_SC03_116", @@ -1240,7 +1538,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2438, - "matchable": 2438 + "matchable": 2438, + "instr_matched": 92611, + "instr_total": 92611 }, { "binary": "ov_SC03_117", @@ -1248,7 +1548,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2557, - "matchable": 2557 + "matchable": 2557, + "instr_matched": 94662, + "instr_total": 94662 }, { "binary": "ov_SC03_118", @@ -1256,7 +1558,9 @@ "shared": 1869, "linked": 0, "byte_identical": 2684, - "matchable": 2684 + "matchable": 2684, + "instr_matched": 99825, + "instr_total": 99825 }, { "binary": "ov_SC03_119", @@ -1264,7 +1568,9 @@ "shared": 1869, "linked": 0, "byte_identical": 2685, - "matchable": 2685 + "matchable": 2685, + "instr_matched": 99825, + "instr_total": 99825 }, { "binary": "ov_SC03_121", @@ -1272,7 +1578,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2459, - "matchable": 2459 + "matchable": 2459, + "instr_matched": 92152, + "instr_total": 92152 }, { "binary": "ov_SC03_124", @@ -1280,7 +1588,9 @@ "shared": 1807, "linked": 0, "byte_identical": 2741, - "matchable": 2741 + "matchable": 2741, + "instr_matched": 100827, + "instr_total": 100827 }, { "binary": "ov_SC03_125", @@ -1288,7 +1598,9 @@ "shared": 1820, "linked": 0, "byte_identical": 2588, - "matchable": 2588 + "matchable": 2588, + "instr_matched": 93943, + "instr_total": 93943 }, { "binary": "ov_SC03_126", @@ -1296,7 +1608,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2423, - "matchable": 2423 + "matchable": 2423, + "instr_matched": 89141, + "instr_total": 89141 }, { "binary": "ov_SC04_000", @@ -1304,7 +1618,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2546, - "matchable": 2546 + "matchable": 2546, + "instr_matched": 93240, + "instr_total": 93240 }, { "binary": "ov_SC04_002", @@ -1312,7 +1628,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2636, - "matchable": 2636 + "matchable": 2636, + "instr_matched": 98451, + "instr_total": 98451 }, { "binary": "ov_SC04_003", @@ -1320,7 +1638,9 @@ "shared": 1818, "linked": 0, "byte_identical": 2502, - "matchable": 2502 + "matchable": 2502, + "instr_matched": 92154, + "instr_total": 92154 }, { "binary": "ov_SC04_004", @@ -1328,7 +1648,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2558, - "matchable": 2558 + "matchable": 2558, + "instr_matched": 94535, + "instr_total": 94535 }, { "binary": "ov_SC04_005", @@ -1336,7 +1658,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2612, - "matchable": 2612 + "matchable": 2612, + "instr_matched": 97876, + "instr_total": 97876 }, { "binary": "ov_SC04_006", @@ -1344,7 +1668,9 @@ "shared": 1817, "linked": 0, "byte_identical": 2454, - "matchable": 2454 + "matchable": 2454, + "instr_matched": 89740, + "instr_total": 89740 }, { "binary": "ov_SC04_007", @@ -1352,7 +1678,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2569, - "matchable": 2569 + "matchable": 2569, + "instr_matched": 95866, + "instr_total": 95866 }, { "binary": "ov_SC04_008", @@ -1360,7 +1688,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2415, - "matchable": 2415 + "matchable": 2415, + "instr_matched": 88648, + "instr_total": 88648 }, { "binary": "ov_SC04_009", @@ -1368,7 +1698,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2441, - "matchable": 2441 + "matchable": 2441, + "instr_matched": 88659, + "instr_total": 88659 }, { "binary": "ov_SC04_010", @@ -1376,7 +1708,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2419, - "matchable": 2419 + "matchable": 2419, + "instr_matched": 88062, + "instr_total": 88062 }, { "binary": "ov_SC04_011", @@ -1384,7 +1718,9 @@ "shared": 1824, "linked": 0, "byte_identical": 2804, - "matchable": 2804 + "matchable": 2804, + "instr_matched": 106658, + "instr_total": 106658 }, { "binary": "ov_SC04_012", @@ -1392,7 +1728,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2420, - "matchable": 2420 + "matchable": 2420, + "instr_matched": 88343, + "instr_total": 88343 }, { "binary": "ov_SC04_015", @@ -1400,7 +1738,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2611, - "matchable": 2611 + "matchable": 2611, + "instr_matched": 94435, + "instr_total": 94435 }, { "binary": "ov_SC04_016", @@ -1408,7 +1748,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2440, - "matchable": 2440 + "matchable": 2440, + "instr_matched": 90006, + "instr_total": 90006 }, { "binary": "ov_SC04_018", @@ -1416,7 +1758,9 @@ "shared": 1896, "linked": 0, "byte_identical": 2857, - "matchable": 2857 + "matchable": 2857, + "instr_matched": 103284, + "instr_total": 103284 }, { "binary": "ov_SC04_019", @@ -1424,7 +1768,9 @@ "shared": 1899, "linked": 0, "byte_identical": 2857, - "matchable": 2857 + "matchable": 2857, + "instr_matched": 103284, + "instr_total": 103284 }, { "binary": "ov_SC04_020", @@ -1432,7 +1778,9 @@ "shared": 1820, "linked": 0, "byte_identical": 2567, - "matchable": 2567 + "matchable": 2567, + "instr_matched": 93290, + "instr_total": 93290 }, { "binary": "ov_SC04_021", @@ -1440,7 +1788,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2423, - "matchable": 2423 + "matchable": 2423, + "instr_matched": 89141, + "instr_total": 89141 }, { "binary": "ov_SC05_000", @@ -1448,7 +1798,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2422, - "matchable": 2422 + "matchable": 2422, + "instr_matched": 88122, + "instr_total": 88122 }, { "binary": "ov_SC05_001", @@ -1456,7 +1808,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2574, - "matchable": 2574 + "matchable": 2574, + "instr_matched": 95793, + "instr_total": 95793 }, { "binary": "ov_SC05_002", @@ -1464,7 +1818,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2442, - "matchable": 2442 + "matchable": 2442, + "instr_matched": 90145, + "instr_total": 90145 }, { "binary": "ov_SC05_003", @@ -1472,7 +1828,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2481, - "matchable": 2481 + "matchable": 2481, + "instr_matched": 92399, + "instr_total": 92399 }, { "binary": "ov_SC05_004", @@ -1480,7 +1838,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2464, - "matchable": 2464 + "matchable": 2464, + "instr_matched": 91442, + "instr_total": 91442 }, { "binary": "ov_SC05_005", @@ -1488,7 +1848,9 @@ "shared": 1825, "linked": 0, "byte_identical": 2491, - "matchable": 2491 + "matchable": 2491, + "instr_matched": 92327, + "instr_total": 92327 }, { "binary": "ov_SC05_006", @@ -1496,7 +1858,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2430, - "matchable": 2430 + "matchable": 2430, + "instr_matched": 89263, + "instr_total": 89263 }, { "binary": "ov_SC05_007", @@ -1504,7 +1868,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2482, - "matchable": 2482 + "matchable": 2482, + "instr_matched": 90670, + "instr_total": 90670 }, { "binary": "ov_SC05_008", @@ -1512,7 +1878,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2543, - "matchable": 2543 + "matchable": 2543, + "instr_matched": 92676, + "instr_total": 92676 }, { "binary": "ov_SC05_009", @@ -1520,7 +1888,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2438, - "matchable": 2438 + "matchable": 2438, + "instr_matched": 88648, + "instr_total": 88648 }, { "binary": "ov_SC05_010", @@ -1528,7 +1898,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2588, - "matchable": 2588 + "matchable": 2588, + "instr_matched": 98815, + "instr_total": 98815 }, { "binary": "ov_SC05_011", @@ -1536,7 +1908,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2409, - "matchable": 2409 + "matchable": 2409, + "instr_matched": 87773, + "instr_total": 87773 }, { "binary": "ov_SC05_017", @@ -1544,7 +1918,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2842, - "matchable": 2842 + "matchable": 2842, + "instr_matched": 103269, + "instr_total": 103269 }, { "binary": "ov_SC05_018", @@ -1552,7 +1928,9 @@ "shared": 1819, "linked": 0, "byte_identical": 2673, - "matchable": 2673 + "matchable": 2673, + "instr_matched": 96740, + "instr_total": 96740 }, { "binary": "ov_SC05_019", @@ -1560,7 +1938,9 @@ "shared": 1815, "linked": 0, "byte_identical": 2423, - "matchable": 2423 + "matchable": 2423, + "instr_matched": 89141, + "instr_total": 89141 }, { "binary": "ov_SC06_000", @@ -1568,7 +1948,9 @@ "shared": 1841, "linked": 0, "byte_identical": 2691, - "matchable": 2691 + "matchable": 2691, + "instr_matched": 98361, + "instr_total": 98361 }, { "binary": "ov_SC06_006", @@ -1576,7 +1958,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2511, - "matchable": 2511 + "matchable": 2511, + "instr_matched": 91906, + "instr_total": 91906 }, { "binary": "ov_SC06_008", @@ -1584,7 +1968,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2542, - "matchable": 2542 + "matchable": 2542, + "instr_matched": 95644, + "instr_total": 95644 }, { "binary": "ov_SC06_010", @@ -1592,7 +1978,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2517, - "matchable": 2517 + "matchable": 2517, + "instr_matched": 96787, + "instr_total": 96787 }, { "binary": "ov_SC06_011", @@ -1600,7 +1988,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2468, - "matchable": 2468 + "matchable": 2468, + "instr_matched": 90283, + "instr_total": 90283 }, { "binary": "ov_SC06_013", @@ -1608,7 +1998,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2425, - "matchable": 2425 + "matchable": 2425, + "instr_matched": 88714, + "instr_total": 88714 }, { "binary": "ov_SC06_014", @@ -1616,7 +2008,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2453, - "matchable": 2453 + "matchable": 2453, + "instr_matched": 89955, + "instr_total": 89955 }, { "binary": "ov_SC06_015", @@ -1624,7 +2018,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2421, - "matchable": 2421 + "matchable": 2421, + "instr_matched": 88633, + "instr_total": 88633 }, { "binary": "ov_SC06_016", @@ -1632,7 +2028,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2549, - "matchable": 2549 + "matchable": 2549, + "instr_matched": 95037, + "instr_total": 95037 }, { "binary": "ov_SC06_018", @@ -1640,7 +2038,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2665, - "matchable": 2665 + "matchable": 2665, + "instr_matched": 109836, + "instr_total": 109836 }, { "binary": "ov_SC06_020", @@ -1648,7 +2048,9 @@ "shared": 1813, "linked": 0, "byte_identical": 2518, - "matchable": 2518 + "matchable": 2518, + "instr_matched": 95150, + "instr_total": 95150 }, { "binary": "ov_SC06_022", @@ -1656,7 +2058,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2642, - "matchable": 2642 + "matchable": 2642, + "instr_matched": 103517, + "instr_total": 103517 }, { "binary": "ov_SC06_024", @@ -1664,7 +2068,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2667, - "matchable": 2667 + "matchable": 2667, + "instr_matched": 105875, + "instr_total": 105875 }, { "binary": "ov_SC06_025", @@ -1672,7 +2078,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2572, - "matchable": 2572 + "matchable": 2572, + "instr_matched": 94908, + "instr_total": 94908 }, { "binary": "ov_SC06_027", @@ -1680,7 +2088,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2408, - "matchable": 2408 + "matchable": 2408, + "instr_matched": 87948, + "instr_total": 87948 }, { "binary": "ov_SC06_029", @@ -1688,7 +2098,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2663, - "matchable": 2663 + "matchable": 2663, + "instr_matched": 102640, + "instr_total": 102640 }, { "binary": "ov_SC06_030", @@ -1696,7 +2108,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2456, - "matchable": 2456 + "matchable": 2456, + "instr_matched": 91949, + "instr_total": 91949 }, { "binary": "ov_SC06_032", @@ -1704,7 +2118,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2658, - "matchable": 2658 + "matchable": 2658, + "instr_matched": 109664, + "instr_total": 109664 }, { "binary": "ov_SC06_033", @@ -1712,7 +2128,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2630, - "matchable": 2630 + "matchable": 2630, + "instr_matched": 107940, + "instr_total": 107940 }, { "binary": "ov_SC07_000", @@ -1720,7 +2138,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2521, - "matchable": 2521 + "matchable": 2521, + "instr_matched": 92470, + "instr_total": 92470 }, { "binary": "ov_SC07_001", @@ -1728,7 +2148,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2454, - "matchable": 2454 + "matchable": 2454, + "instr_matched": 91362, + "instr_total": 91362 }, { "binary": "ov_SC07_002", @@ -1736,7 +2158,9 @@ "shared": 1816, "linked": 0, "byte_identical": 2579, - "matchable": 2579 + "matchable": 2579, + "instr_matched": 96657, + "instr_total": 96657 }, { "binary": "ov_SC07_006", @@ -1744,7 +2168,9 @@ "shared": 1630, "linked": 0, "byte_identical": 2457, - "matchable": 2457 + "matchable": 2457, + "instr_matched": 100506, + "instr_total": 100506 }, { "binary": "ov_SC07_007", @@ -1752,7 +2178,9 @@ "shared": 1666, "linked": 0, "byte_identical": 2612, - "matchable": 2612 + "matchable": 2612, + "instr_matched": 93027, + "instr_total": 93027 }, { "binary": "ov_SC07_008", @@ -1760,7 +2188,9 @@ "shared": 1812, "linked": 0, "byte_identical": 2386, - "matchable": 2386 + "matchable": 2386, + "instr_matched": 87127, + "instr_total": 87127 }, { "binary": "ov_SC07_009", @@ -1768,7 +2198,9 @@ "shared": 1811, "linked": 0, "byte_identical": 2430, - "matchable": 2430 + "matchable": 2430, + "instr_matched": 87808, + "instr_total": 87808 }, { "binary": "ov_SC07_010", @@ -1776,7 +2208,9 @@ "shared": 1689, "linked": 0, "byte_identical": 2523, - "matchable": 2523 + "matchable": 2523, + "instr_matched": 92039, + "instr_total": 92039 }, { "binary": "ov_SC07_011", @@ -1784,7 +2218,9 @@ "shared": 1664, "linked": 0, "byte_identical": 2448, - "matchable": 2448 + "matchable": 2448, + "instr_matched": 88375, + "instr_total": 88375 } ] } diff --git a/phase-ends/CURRENT_PHASE.md b/phase-ends/CURRENT_PHASE.md index 8f1722832..b93b341fd 100644 --- a/phase-ends/CURRENT_PHASE.md +++ b/phase-ends/CURRENT_PHASE.md @@ -73,7 +73,7 @@ one-time snapshot, `CLAUDE.md` gains "never `git clean -x`" (R20 amendment propo - [ ] **C10** Support purge → probe gate → FLIP (Drew) — decision Max - [x] **D1** README rewrite — Max — see Log 2026-09-07 D1 - [x] **D2** LICENSE + `src/NOTICE.md` + `THIRD_PARTY.md` — Max wording — see Log 2026-09-07 D2 -- [ ] **D3** Progress publishing (progress.json, badges, frogress_upload, objdiff_report + progress.yml) — xHigh +- [x] **D3** Progress publishing (progress.json, badges, frogress_upload, objdiff_report + progress.yml) — xHigh — see Log 2026-09-07 D3 - [ ] **D4** SETUP.md public-clean pass — xHigh - [ ] **D5** Governing-docs consistency pass + `tools/doc_links.py` — xHigh - [ ] **F1** timeline.py + story — xHigh tool / Max narrative @@ -374,14 +374,26 @@ Mid-phase rules check after every 4 completed tasks (P6). Commit banked artifact never distributed; the AP world cited as facts). `tools/README.md` (new): the one AGPL statement for `tools/`, no per-file SPDX headers. **For Drew:** `docs/history/project_architect_v1.3.0.md` is KEPT as the historical record of the framework version used (THIRD_PARTY row links the repo) — say if you prefer link-only. Commit: see below. +- **2026-09-07 (S87) — D3 progress publishing.** `progress.py`: `weighted_metrics` now returns per-binary instruction totals + (`per_bin`, from the existing loop), `--json` rows carry `instr_matched/instr_total` (main 45,150/45,150, resident + 4,483/4,483 — known-true check), and `docs/badges/{fleet_instr,fleet_fn,distinct,binaries}.json` are written in the shields + endpoint format; `--check` also asserts the badges (control: a mutated badge → STALE). `make audit-digest` runs + `progress.py --json --readme --check`. `tools/objdiff_report.py`: report.proto v2 (snake_case) — 218 units all complete, + code 53,968,452/53,968,452 bytes (= 13,492,113 × 4, reconciles), functions 363,214/363,214, categories `game-code` + + `linked-sony-objects`; **validated with the real `objdiff-cli` 3.8.1** (`report changes a a` parses and reports no change; + a mutated unit is reported — control) — its `changes` takes POSITIONAL previous/current. `tools/frogress_upload.py`: dry run + prints the payload (git_hash, timestamp, the measures with denominators); `--push` needs `FROGRESS_API_SECRET`. + `.github/workflows/progress.yml`: converts the committed JSON, uploads `SLUS_007.26_report` (no rebuild in CI). SETUP: 3 + inventory rows + a P33 D1–D3 section (R21). Outward (Drew, after the flip): decomp.dev registration, frogress slug + key. + Commit: see below. -## 🛑 SESSION CHECKPOINT — A1–A5 ✓, B1–B9/C3 ✓, C1–C9 ✓, D1–D2 ✓; C10 IN PROGRESS ON DREW'S SIDE (the Support ticket + the daily probe); NEXT = D3 (2026-09-07 ~07:50 UTC, written by session fa49faf3 "S87" after the D2 commit; SUPERSEDES the earlier blocks) +## 🛑 SESSION CHECKPOINT — A1–A5 ✓, B1–B9/C3 ✓, C1–C9 ✓, D1–D3 ✓; C10 IN PROGRESS ON DREW'S SIDE (the Support ticket + the daily probe); NEXT = D4 (2026-09-07 ~08:20 UTC, written by session fa49faf3 "S87" after the D3 commit; SUPERSEDES the earlier blocks) ### 0. How to use this block You are a FRESH SESSION that has read `PROJECT_CONTEXT.md`, `phase-ends/DIGEST.md`, `PhaseEnd_Phase30/31/32.md` and this file, and nothing else (R64). Replay this block verbatim, state phase / done / NEXT / effort, list the rules from the digest -(R1–R73), then WAIT for Drew. **NEXT = two tracks.** **Drew (C10):** open the GitHub Support ticket (text in `docs/public-flip-runbook.md` §11), then run `tools/public_rewrite/probe_github.sh` daily (gh is authenticated in WSL; 31 of 33 sampled old hashes were alive at S87's baseline) until it prints PASS — only then the visibility flip, and only after Blocks D/E/F have landed. **Claude (NEXT = D3, xHigh + one Max pass on the metric→schema map):** `progress.json` exists (D1); add `docs/badges/fleet_instr.json` + `docs/badges/binaries.json` in shields endpoint format (`{"schemaVersion":1,"label","message","color"}`, written by `progress.py --json`, the README already references exactly these names); extend `make audit-digest` with `progress.py --json --readme --check`; `tools/frogress_upload.py` (stdlib, `--dry-run` default, `FROGRESS_API_SECRET` env; frogress projects are admin-created — Drew requests slug `bfm` + key later); `tools/objdiff_report.py` (progress.json → objdiff `report.json`, categories `game-code` vs `linked-sony-objects`, metadata "from a local clean rebuild; CI does not rebuild") + `.github/workflows/progress.yml` uploading artifact `SLUS_007.26_report` (verify the JSON parses with a downloaded `objdiff-cli` first — X2 data). Then D4 → D5 → F1 → F2 → F3 → E3 → E4 → E5 → E6 on the still-private repo; E1/E2 and D3's outward actions after the flip. **Every commit cites NEW hashes only; `.run/public_rewrite/` (scratch: dict, mailmap, old-to-new, bundle 556 MB, the rewritten bare clone) holds the old ones — keep until the probe passes, then delete (C11).** -one TaskCreate per plan item A1…G2, 40 items, mark A1–A5 + B1–B9/C3 + C1–C9 + D1–D2 completed; R28). The SessionStart hook restarts the headless +(R1–R73), then WAIT for Drew. **NEXT = two tracks.** **Drew (C10):** open the GitHub Support ticket (text in `docs/public-flip-runbook.md` §11), then run `tools/public_rewrite/probe_github.sh` daily (gh is authenticated in WSL; 31 of 33 sampled old hashes were alive at S87's baseline) until it prints PASS — only then the visibility flip, and only after Blocks D/E/F have landed. **Claude (NEXT = D4, xHigh): the SETUP.md public-clean pass** — header date; §2.3/§2.4 → download-only wording (drop the "vendored zip" lines the plan cites at 16-17/861-862 — grep `vendored`); §4.4 a generic dump path; §4.7 the tarballs; §4.8 + §5.6 PsyQ = user-supplied; §6.5 → the decomp.me preset (E1); the "Backup & private-repo posture" section → the PUBLIC posture (R1/R20 historical; the archive repo; `config/ghidra/` as R20's home — the P33 paragraph is already there, the private-era prose above it is not); ledger rows 11/14 closed; an R21 row for every P33 tool (audit against `git log --diff-filter=A --name-only -- tools/`); every `gitignored|private|curated public mirror|two-repo` mention reviewed line by line. Then D5 (governing docs + `tools/doc_links.py`) → F1 → F2 → F3 → E3 → E4 → E5 → E6; E1/E2 and D3's outward actions after the flip. **Every commit cites NEW hashes only; `.run/public_rewrite/` (scratch: dict, mailmap, old-to-new, bundle 556 MB, the rewritten bare clone) holds the old ones — keep until the probe passes, then delete (C11).** +one TaskCreate per plan item A1…G2, 40 items, mark A1–A5 + B1–B9/C3 + C1–C9 + D1–D3 completed; R28). The SessionStart hook restarts the headless MCP server when `ghidra/bfm.rep` exists (it did not stay up in S87 — `ss -tln` showed nothing on :8080; harmless): B6/B7/B8 need no Ghidra; run `tools/ghidra_mcp_stop.sh` before any headless step (R23). @@ -417,15 +429,16 @@ still stand for the tasks ahead — restate them, Drew decides (R7/R27). 1. **C10** (Drew; decision Max): the Support ticket (text in `docs/public-flip-runbook.md` §11), then `tools/public_rewrite/ probe_github.sh` daily until PASS (gh auth done in S87; `old-to-new.tsv` + `old_tag_tip.txt` in scratch); the flip only after the probe passes AND Blocks D/E/F have landed. -2. **D3 — progress publishing** (see the NEXT line above): badges JSON (2 files, exact names), audit-digest extension, - frogress_upload.py, objdiff_report.py + progress.yml. Log, tick, refresh, commit. Then **D4** (SETUP.md public-clean - pass: header date; §2.3/§2.4 download-only wording — the "vendored zip" lines; §4.4 generic dump path; §4.7; §4.8/§5.6 - PsyQ user-supplied; §6.5 → the decomp.me preset; the "Backup & private-repo posture" section → the public posture; - ledger rows 11/14; R21 rows for every P33 tool) and **D5** (governing-docs consistency + `tools/doc_links.py`). +2. **D4 — SETUP.md public-clean pass** (xHigh; see the NEXT line above). Then **D5**: CLAUDE.md:61 wording (true again), + `.gitignore` header, `dumps/INDEX.md:8`, `docs/roadmap-to-100.md` §1 → a dated "status at P33" block, `docs/gen2-roadmap.md` + Phase-14 → a "SUPERSEDED at P33" banner, `phase-ends/DIGEST.md` §0/§1/§3 (H1 re-tightened, R1/R20 historical, the + PROJECT_CONTEXT corrections, R65–R73 full text — already there), `docs/backlog.md` (0 rows — done); NEW `tools/doc_links.py` + (relative link/path checker over README, THIRD_PARTY, SETUP, verification, the runbook, the wiki; in tools-health) + a + line-by-line grep review for `gitignored|private|curated public mirror|two-repo`. 3. Aftercare reminders (C11): `gh auth logout` in WSL after the flip; `git remote remove archive`; other clones reset, never pull; `.run/public_rewrite/` deleted after the probe passes (keep the bundle off-machine if wanted). ### 4. Files S87 touched -D2: `LICENSE` (new), `src/NOTICE.md` (new), `THIRD_PARTY.md` (new), `tools/README.md` (new). D1: `README.md` (rewritten), `docs/progress.json` (new, generated), `tools/progress.py` (`--json`/`--readme`/`--check`), `Makefile` (report wiring). C9: `tools/public_rewrite/probe_github.sh` (422 = gone), `docs/public-flip-runbook.md` §10/§12; `.git` (the archive remote removed, 12 worktrees removed, repacked to one 80 MB pack). C8: `.run/P33/verify/*` (the recorded run, tracked), `docs/verification.md` §2, `docs/family-hseq.md`, `tools/verify_contract.sh` (the step-00 fix). C4–C7: `docs/commit-map.tsv` (new), the 98 token-resolved files (see the C7 entry), `tools/public_rewrite/resolve_tokens.py` (the skip rule), `.git/config` (repo-local noreply identity). Scratch `.run/public_rewrite/`: `pre-rewrite.bundle`, `repo.git` (the rewritten bare clone, keep until C9), `c4c5.{sh,log}`, `old-to-new.tsv`, `unchanged_commits.txt`, `old_tag_tip.txt`, `c5_commit-map.tsv`, `ids_after.txt`, `refs_*.txt`. C1: `tools/public_rewrite/{common,hash_dict,scrub,gate_scan,run_filter,verify_rewrite,build_commit_map,resolve_tokens,absent_scan}.py`, `probe_github.sh`, `expected_offenders.txt` (all new), `requirements-python.txt`, `docs/SETUP.md`, `docs/public-flip-runbook.md`. Scratch `.run/public_rewrite/`: `dict.json`, `mailmap`, `rom_blob_ids.txt`, `old_tag_tip.txt`, `trial*.{sh,log}`, `trial_commit-map.tsv`, `trial_old-to-new.tsv`, `unchanged_commits.txt`, `nonpurge_blob_ids.txt`, `filter.log`. B9/C3: 251 index removals (files on disk), `docs/public-flip-runbook.md` (new), `docs/SETUP.md` §2.3/§2.4, `docs/verification.md`, `CLAUDE.md`, `docs/decision-log.md`. A5: `tools/verify_contract.sh` (new), `tools/audit_frontier.py` (derived denominator lines), `.gitignore` (the `.run/P33/verify/` allowlist), `.run/P33/verify/*` (tracked evidence), `docs/verification.md` §2, regenerated `docs/family-hseq.md` + `docs/progress*.md`/`duplicates*.md`. B8: `docs/verification.md` (new), `docs/SETUP.md` (§4.4/§4.6/§4.8/§6.3 pointers, backup posture). B7: `.github/workflows/no-rom.yml`, `tools/audit_public.py`, `tools/compile_only.py`, `tools/public_rewrite/purge_set.txt` (all new), `docs/SETUP.md`. B6: `dumps/CHECKSUMS.sha1` (new), `dumps/INDEX.md`, `docs/memory-map.md`. B5: `tools/ghidra_scripts/ImportAnnotations.java` (3 compile fixes + the `/undefined` resolver), `tools/ghidra_rebuild.sh` +D3: `tools/progress.py` (per_bin, badges, --check), `docs/badges/*.json` (4, new), `docs/progress.json`, `tools/objdiff_report.py` (new), `tools/frogress_upload.py` (new), `.github/workflows/progress.yml` (new), `Makefile` (audit-digest), `docs/SETUP.md`. Scratch: `.run/objdiff/` (the objdiff-cli 3.8.1 validator + reports). D2: `LICENSE` (new), `src/NOTICE.md` (new), `THIRD_PARTY.md` (new), `tools/README.md` (new). D1: `README.md` (rewritten), `docs/progress.json` (new, generated), `tools/progress.py` (`--json`/`--readme`/`--check`), `Makefile` (report wiring). C9: `tools/public_rewrite/probe_github.sh` (422 = gone), `docs/public-flip-runbook.md` §10/§12; `.git` (the archive remote removed, 12 worktrees removed, repacked to one 80 MB pack). C8: `.run/P33/verify/*` (the recorded run, tracked), `docs/verification.md` §2, `docs/family-hseq.md`, `tools/verify_contract.sh` (the step-00 fix). C4–C7: `docs/commit-map.tsv` (new), the 98 token-resolved files (see the C7 entry), `tools/public_rewrite/resolve_tokens.py` (the skip rule), `.git/config` (repo-local noreply identity). Scratch `.run/public_rewrite/`: `pre-rewrite.bundle`, `repo.git` (the rewritten bare clone, keep until C9), `c4c5.{sh,log}`, `old-to-new.tsv`, `unchanged_commits.txt`, `old_tag_tip.txt`, `c5_commit-map.tsv`, `ids_after.txt`, `refs_*.txt`. C1: `tools/public_rewrite/{common,hash_dict,scrub,gate_scan,run_filter,verify_rewrite,build_commit_map,resolve_tokens,absent_scan}.py`, `probe_github.sh`, `expected_offenders.txt` (all new), `requirements-python.txt`, `docs/SETUP.md`, `docs/public-flip-runbook.md`. Scratch `.run/public_rewrite/`: `dict.json`, `mailmap`, `rom_blob_ids.txt`, `old_tag_tip.txt`, `trial*.{sh,log}`, `trial_commit-map.tsv`, `trial_old-to-new.tsv`, `unchanged_commits.txt`, `nonpurge_blob_ids.txt`, `filter.log`. B9/C3: 251 index removals (files on disk), `docs/public-flip-runbook.md` (new), `docs/SETUP.md` §2.3/§2.4, `docs/verification.md`, `CLAUDE.md`, `docs/decision-log.md`. A5: `tools/verify_contract.sh` (new), `tools/audit_frontier.py` (derived denominator lines), `.gitignore` (the `.run/P33/verify/` allowlist), `.run/P33/verify/*` (tracked evidence), `docs/verification.md` §2, regenerated `docs/family-hseq.md` + `docs/progress*.md`/`duplicates*.md`. B8: `docs/verification.md` (new), `docs/SETUP.md` (§4.4/§4.6/§4.8/§6.3 pointers, backup posture). B7: `.github/workflows/no-rom.yml`, `tools/audit_public.py`, `tools/compile_only.py`, `tools/public_rewrite/purge_set.txt` (all new), `docs/SETUP.md`. B6: `dumps/CHECKSUMS.sha1` (new), `dumps/INDEX.md`, `docs/memory-map.md`. B5: `tools/ghidra_scripts/ImportAnnotations.java` (3 compile fixes + the `/undefined` resolver), `tools/ghidra_rebuild.sh` (`.proof` markers; dies unless `failed=0`), `tools/ghidra_annotations_delta.py` (the three drift classes), new `tools/ghidra_roster.py`, `tools/ghidra_mcp_start.sh` (silent no-op guard), `.claude/settings.json` (relative hooks), `Makefile` (roster check in tools-health), `docs/SETUP.md` (P33 B5 section, 5 inventory rows, §2.8), `config/ghidra/*` diff --git a/tools/frogress_upload.py b/tools/frogress_upload.py new file mode 100644 index 000000000..f5d0bda8e --- /dev/null +++ b/tools/frogress_upload.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python3 +"""frogress_upload.py — push docs/progress.json to a frogress instance (progress.deco.mp) (P33 D3). + + tools/frogress_upload.py # --dry-run is the default: prints the payload, sends nothing + tools/frogress_upload.py --push --project bfm --version us # needs FROGRESS_API_SECRET in the environment + +frogress projects are created by the frogress maintainers (a slug + an API key are issued to the project owner); +the upload is `POST https://progress.deco.mp/data///` with a JSON body +`{"api_key": …, "entries": [{"git_hash": …, "timestamp": …, "categories": {"default": {measure: value, …}}}]}` +(schema as documented by decomp.me's frogress; treat the endpoint's answer as data, X2). Measures sent, every one with +its denominator (R41): functions / instructions / distinct code / main game code matched and total, binaries +byte-identical and total. Stdlib only. The secret is never written anywhere; a missing secret with --push is an error. +""" +import argparse +import json +import os +import pathlib +import subprocess +import sys +import urllib.request + +REPO = pathlib.Path(__file__).resolve().parent.parent + + +def payload(d, git_hash, ts, key): + f, c = d["fleet"], d["counts"] + ok_bins = sum(1 for r in d["per_binary"] if r["matchable"] and r["byte_identical"] == r["matchable"]) + m = { + "fns_matched": f["fn_count"]["matched"], "fns_total": f["fn_count"]["total"], + "instr_matched": f["instr_weighted"]["matched"] if f["instr_weighted"] else 0, + "instr_total": f["instr_weighted"]["total"] if f["instr_weighted"] else 0, + "distinct_matched": f["distinct_code"]["matched"] if f["distinct_code"] else 0, + "distinct_total": f["distinct_code"]["total"] if f["distinct_code"] else 0, + "main_matched": f["main_game_code"]["matched"] if f["main_game_code"] else 0, + "main_total": f["main_game_code"]["total"] if f["main_game_code"] else 0, + "binaries_ok": ok_bins, "binaries_total": d["binaries"], + "linked_sony_functions": c["linked_psyq_objects"], "verbatim_asm_bodies": c["verbatim_asm_bodies"], + } + return {"api_key": key, "entries": [{"git_hash": git_hash, "timestamp": ts, "categories": {"default": m}}]} + + +def main(argv): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--push", action="store_true", help="actually POST (default: dry run)") + ap.add_argument("--project", default="bfm") + ap.add_argument("--version", default="us") + ap.add_argument("--url", default="https://progress.deco.mp") + ap.add_argument("--in", dest="inp", default=str(REPO / "docs/progress.json")) + a = ap.parse_args(argv) + d = json.loads(pathlib.Path(a.inp).read_text(encoding="utf-8")) + git_hash = subprocess.run(["git", "-C", str(REPO), "rev-parse", "HEAD"], capture_output=True, text=True).stdout.strip() + ts = int(subprocess.run(["git", "-C", str(REPO), "log", "-1", "--format=%ct"], capture_output=True, text=True).stdout.strip() or 0) + key = os.environ.get("FROGRESS_API_SECRET", "") + body = payload(d, git_hash, ts, key if a.push else "") + endpoint = f"{a.url.rstrip('/')}/data/{a.project}/{a.version}/" + if not a.push: + print(f"frogress_upload: DRY RUN — would POST to {endpoint}:") + print(json.dumps(body, indent=1)) + return 0 + if not key: + sys.exit("frogress_upload: --push needs FROGRESS_API_SECRET in the environment (never in a file)") + req = urllib.request.Request(endpoint, data=json.dumps(body).encode(), headers={"Content-Type": "application/json"}, method="POST") + with urllib.request.urlopen(req, timeout=60) as resp: + text = resp.read().decode("utf-8", "replace") + print(f"frogress_upload: HTTP {resp.status} {text[:300]}") + return 0 if 200 <= resp.status < 300 else 1 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/tools/objdiff_report.py b/tools/objdiff_report.py new file mode 100644 index 000000000..974a3680d --- /dev/null +++ b/tools/objdiff_report.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +"""objdiff_report.py — docs/progress.json → an objdiff progress report (report.json) for decomp.dev (P33 D3). + + tools/objdiff_report.py [--out report.json] [--in docs/progress.json] + +decomp.dev reads a GitHub Actions artifact in objdiff's report format (objdiff-core/protos/report.proto, `Report` +version 2): top-level `measures`, one `units` entry per binary with its own measures and metadata, and `categories`. +Field names are the proto's (snake_case); the output was validated with `objdiff-cli report changes` (S87). + +What the numbers ARE here (every one carries its denominator in docs/progress.json, R41): + * code = instructions × 4 bytes (MIPS): `total_code` / `matched_code` per binary from the build-derived function + boundaries; main's code is its GAME CODE only (the linked Sony objects are a separate functions-only category); + * functions = byte-identical / matchable per binary (REAL C + LINKED Sony objects + empties); + * `fuzzy_match_percent` == the exact matched percentage (this project has no fuzzy state: a function is byte-identical + or it is an assembly stub); + * categories: `game-code` (every binary's game code) and `linked-sony-objects` (the 1,256 PsyQ functions of the main + executable — byte-identical by link, not our C; counted in functions only, their byte size is not measured here). +The report is derived from a LOCAL clean rebuild recorded in docs/progress.json (`make report`); CI does not rebuild the +game (it has no disc) — the workflow only converts the committed JSON and uploads the artifact. +""" +import argparse +import json +import pathlib +import sys + +REPO = pathlib.Path(__file__).resolve().parent.parent +VERSION = 2 + + +def measures(code_m, code_t, fn_m, fn_t, units_t=0, units_c=0): + pct = lambda m, t: (100.0 * m / t) if t else 0.0 + return { + "fuzzy_match_percent": round(pct(code_m, code_t), 4), + "total_code": int(code_t), "matched_code": int(code_m), "matched_code_percent": round(pct(code_m, code_t), 4), + "total_data": 0, "matched_data": 0, "matched_data_percent": 0.0, + "total_functions": int(fn_t), "matched_functions": int(fn_m), "matched_functions_percent": round(pct(fn_m, fn_t), 4), + "complete_code": int(code_m), "complete_code_percent": round(pct(code_m, code_t), 4), + "complete_data": 0, "complete_data_percent": 0.0, + "total_units": int(units_t), "complete_units": int(units_c), + } + + +def build(d): + units, cm_all, ct_all, fm_all, ft_all, complete = [], 0, 0, 0, 0, 0 + game_fm = game_ft = 0 + for r in d["per_binary"]: + im, it = r.get("instr_matched"), r.get("instr_total") + if im is None or it is None: + sys.exit(f"objdiff_report: {r['binary']} has no instruction totals in progress.json — regenerate it with the sigs present (make report BINARY=main)") + code_m, code_t = im * 4, it * 4 + fn_m, fn_t = r["byte_identical"], r["matchable"] + game_fn_t = fn_t - r["linked"] + game_fn_m = fn_m - r["linked"] # every linked object is byte-identical by construction + done = bool(fn_t) and fn_m == fn_t + units.append({ + "name": r["binary"], + "measures": measures(code_m, code_t, fn_m, fn_t, 1, 1 if done else 0), + "sections": [{"name": ".text", "size": code_t, "fuzzy_match_percent": round(100.0 * code_m / code_t, 4) if code_t else 0.0}], + "functions": [], + "metadata": {"complete": done, "module_name": r["binary"], + "source_path": "src" if r["binary"] == "main" else f"src/{r['binary']}", + "progress_categories": ["game-code"] + (["linked-sony-objects"] if r["linked"] else []), + "auto_generated": False}, + }) + cm_all += code_m; ct_all += code_t; fm_all += fn_m; ft_all += fn_t; complete += int(done) + game_fm += game_fn_m; game_ft += game_fn_t + linked = d["counts"]["linked_psyq_objects"] + return { + "version": VERSION, + "measures": measures(cm_all, ct_all, fm_all, ft_all, len(units), complete), + "units": units, + "categories": [ + {"id": "game-code", "name": "Game code (our C)", "measures": measures(cm_all, ct_all, game_fm, game_ft, len(units), complete)}, + {"id": "linked-sony-objects", "name": "Sony PsyQ library objects (linked, not our C)", + "measures": measures(0, 0, linked, linked, 1, 1)}, + ], + } + + +def main(argv): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--in", dest="inp", default=str(REPO / "docs/progress.json")) + ap.add_argument("--out", default="report.json") + a = ap.parse_args(argv) + d = json.loads(pathlib.Path(a.inp).read_text(encoding="utf-8")) + if d.get("schema") != 1: + sys.exit(f"objdiff_report: unexpected progress.json schema {d.get('schema')!r} (R43)") + rep = build(d) + pathlib.Path(a.out).write_text(json.dumps(rep, indent=1) + "\n", encoding="utf-8") + m = rep["measures"] + print(f"objdiff_report: {len(rep['units'])} units ({m['complete_units']} complete), code {m['matched_code']:,}/{m['total_code']:,} bytes " + f"= {m['matched_code_percent']:.2f}%, functions {m['matched_functions']:,}/{m['total_functions']:,} -> {a.out}") + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/tools/progress.py b/tools/progress.py index f9bc0e2bd..2cb9fcd9d 100644 --- a/tools/progress.py +++ b/tools/progress.py @@ -925,16 +925,20 @@ def weighted_metrics(): fm = ft = 0 cls_nins, matched_cls = {}, set() + per_bin = {} # P33 D3: binary -> [matched ins, total ins] (the objdiff units) for p in paths: - st = stub_addrs(_sig_binary(p)) + b = _sig_binary(p) + st = stub_addrs(b) + bm = bt = 0 for line in open(p): r = json.loads(line) a, n, hx = int(r["addr"], 16), r["nins"], r["h_exact"] - ft += n + ft += n; bt += n cls_nins[hx] = n # h_exact-identical -> identical nins if a not in st: # non-stub == matched (fleet is byte-identical) - fm += n + fm += n; bm += n matched_cls.add(hx) + per_bin[b] = [bm, bt] ut = sum(cls_nins.values()) um = sum(n for hx, n in cls_nins.items() if hx in matched_cls) @@ -994,7 +998,8 @@ def weighted_metrics(): # main's open stubs in `frontier_classify` (a known-true-case check). fleet_m_all, fleet_t_all = fm + mm, ft + mt dedup_m_all, dedup_t_all = um + mm, ut + mt # main's fns are unique — no h_exact sharing - return dict(fleet_m=fleet_m_all, fleet_t=fleet_t_all, + per_bin["main"] = [mm, mt] + return dict(fleet_m=fleet_m_all, fleet_t=fleet_t_all, per_bin=per_bin, fleet_pct=(100 * fleet_m_all / fleet_t_all if fleet_t_all else 0.0), dedup_m=dedup_m_all, dedup_t=dedup_t_all, dedup_pct=(100 * dedup_m_all / dedup_t_all if dedup_t_all else 0.0), @@ -1101,10 +1106,40 @@ def fleet(): "verbatim_asm_bodies": nverb, "include_asm_stubs": STUBS, "non_matching": NM, "matchable": MATCH, "dedup_groups": ngroups, "dedup_instances": nmembers}, "per_binary": [{"binary": r['binary'], "real": r['real'], "shared": r['shared'], "linked": r['linked'], - "byte_identical": r['byteident'], "matchable": r['matchable']} for r in rows], + "byte_identical": r['byteident'], "matchable": r['matchable'], + "instr_matched": (wm['per_bin'].get(r['binary'], [None, None])[0] if wm else None), + "instr_total": (wm['per_bin'].get(r['binary'], [None, None])[1] if wm else None)} for r in rows], } +def badge(label, message, pct): + color = "brightgreen" if pct >= 99.95 else "green" if pct >= 75 else "yellow" if pct >= 50 else "orange" + return {"schemaVersion": 1, "label": label, "message": message, "color": color} + + +def badge_files(d): + """{name: json text} for docs/badges/*.json in the shields.io endpoint format (README: + img.shields.io/endpoint?url=…). Names are fixed: the README references exactly these files.""" + import json as _json + f, c = d["fleet"], d["counts"] + ok_bins = sum(1 for r in d["per_binary"] if r["matchable"] and r["byte_identical"] == r["matchable"]) + files = { + "fleet_instr.json": badge("matched (instructions)", f"{f['instr_weighted']['pct']:.1f}%", f['instr_weighted']['pct']) if f['instr_weighted'] else None, + "fleet_fn.json": badge("matched (functions)", f"{f['fn_count']['pct']:.2f}%", f['fn_count']['pct']), + "distinct.json": badge("distinct code matched", f"{f['distinct_code']['pct']:.1f}%", f['distinct_code']['pct']) if f['distinct_code'] else None, + "binaries.json": badge("byte-identical binaries", f"{ok_bins}/{d['binaries']}", 100.0 * ok_bins / d['binaries']), + } + return {n: _json.dumps(v) + "\n" for n, v in files.items() if v is not None} + + +def write_badges(d): + bd = ROOT / "docs/badges"; bd.mkdir(exist_ok=True) + files = badge_files(d) + for name, text in files.items(): + (bd / name).write_text(text) + return sorted(files) + + README_BEGIN, README_END = "", "" @@ -1140,8 +1175,13 @@ def write_json_and_readme(check=False): if check: if not jp.exists() or jp.read_text() != text: sys.exit("progress.py --json --check: docs/progress.json is STALE — run `make report BINARY=main`") + for name, want in badge_files(d).items(): + bp = ROOT / "docs/badges" / name + if not bp.exists() or bp.read_text() != want: + sys.exit(f"progress.py --check: docs/badges/{name} is STALE or missing — run `make report BINARY=main`") else: jp.write_text(text) + write_badges(d) rp = ROOT / "README.md" if not rp.exists(): sys.exit("progress.py --readme: README.md missing")