Body normalisation: per-method similarity score + leaf delta

Turns the dispatch axis from a binary changed/unchanged into a "how much" measure
of code change — the original goal. ams.normalize compares two body fingerprints
(the ordered leaf-call anchors) with difflib after collapsing consecutive-duplicate
anchors (a load-twice codegen artefact), yielding a 0-100 similarity and the exact
leaves that appeared/vanished.

Every dispatch `changed` entry now carries body={similarity, added, removed}, and the
block carries a summary={shared, identical, changed, mean_similarity}.

Golden pair (cross-compiler): 470 shared bodies, 131 identical, mean 66% similar;
Animo SHOW/HIDE/PAUSE/RESUME come out 100% despite MSVC6 vs MSVC8, LOAD 50% with the
swapped leaves spelled out.

- normalize.py: canonical / body_similarity / body_delta
- diff: _dispatch_diff enriches changed with body + adds summary
- render: METHOD BODIES shows %, leaf delta, summary line
- UI: similarity % + leaf delta + axis summary
- tests: 5 new -> 34/34

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Patryk Gensch
2026-05-31 13:23:15 +02:00
parent 27399a52b1
commit b0d3d22445
7 changed files with 198 additions and 18 deletions

View File

@@ -110,6 +110,13 @@ każdej metody — wykrywa **zmiany ciała** między wersjami; jak `struct_layou
między wersjami tego samego kompilatora (cross-compiler proste metody i tak się zgadzają,
np. Animo `SHOW``vtbl+0xa0` na MSVC6 i MSVC8).
**Normalizacja ciał** (`ams.normalize`): każda zmiana w osi `dispatch` niesie wynik
`body = {similarity, added, removed}` — podobieństwo 0100% sekwencji liści (`difflib`,
po zwinięciu sąsiednich duplikatów = artefaktów codegenu) oraz *które* wywołania doszły/zniknęły.
Blok dostaje też `summary` (wspólne / identyczne / zmienione / średnie podobieństwo). Na golden
pair (cross-compiler): 470 wspólnych ciał, 131 identycznych, średnio 66% — a `SHOW/HIDE/PAUSE/
RESUME` Animo wychodzą 100% mimo MSVC6↔MSVC8. To jest miara „na ile się zmieniło" na poziomie kodu.
## Backend (FastAPI + katalog)
Modularny monolit nad SQLAlchemy — domyślnie SQLite (zero setupu), gotowy pod Postgres