# Current reconstruction handoff This file records only the current durable state. Historical investigations belong in focused notes such as `RUNECL_FUNCTION_EXACT_NOTES.md`; live counts come from the ledgers, not this prose. ## Current status As cold-built and replayed on 2026-08-20 against the original Japanese TH08 1.00d target: - authored source: **1,107 / 1,107 functions**, **459,757 / 459,757 bytes**; - strict authored exact: **1,091 / 1,107 functions**, **445,728 / 459,757 bytes**; - library inventory: **1,115 classified functions**; all **1,115 / 1,115** now have mapping sizes totaling **216,820 bytes**; the independent library exact ledger currently accepts **172 functions / 27,280 body bytes**; - `config/claims.csv` is header-only; - a cold normal VC7 build links `build/th08.exe` successfully; - a cold objdiff build followed by full replay passes **1,091 / 1,091** accepted units; - repository-owned target-independent CI passes. Regenerate or verify these values with: ```bash python3 scripts/analysis/report-reconstruction-status.py --summary python3 scripts/validate-tracking.py --require-target python3 scripts/analysis/verify-exact-units.py --all --json \ > build/accepted-unit-replay.json python3 scripts/progress.py --check python3 scripts/ci.py ``` `verify-exact-units.py --all` performs its own single-job cold build. Do not add `--reuse-build` when attesting aggregate totals. ## Authored exact backlog Two functions were already deferred and have never been accepted. Do not count them as exact or restart broad brute-force matrices without a new target-backed hypothesis. - `ReplayManager::OnUpdateHighPrioDemo2 @ 0x004526C0`, 361 bytes: the natural source object is one byte longer and the residual is a register-allocation phase difference. Its adjacent callback family is exact. - `TitleScreen::RegisterChain @ 0x0047146D`, 281 bytes: target and object have the same extent; five stack-displacement bytes differ because the target frame is `0x40` while the current natural object frame is `0x5C`. The source for both is present and behaviorally reconstructed. Exact coverage will increase only when the canonical comparator returns `exact` for a natural, evidence-backed C++ form. Fourteen additional rows were removed from `config/matches.csv` after the cold aggregate replay showed that their historical build objects no longer reproduced. Their configured units remain in `config/match-units.toml` as diagnostic starting points; they are not accepted claims. | Address | Unit | Cold-build result class | | --- | --- | --- | | `0x00402600` | `accepted-exact-00402600` | caller bytes/relocations differ | | `0x00405420` | `ascii-manager-on-draw-high-prio-impl` | relocation symbol drift | | `0x00406580` | `main-exact-00406580` | configured COMDAT absent from `main.obj` | | `0x004069F0` | `manual-comdat-exact-004069f0` | configured COMDAT symbol drift | | `0x0040EC00` | `anm-vm-set-z-rotation` | object `0x2D`, target `0x2B` | | `0x00439B29` | `game-manager-roi-exact-00439b29` | object `0x8F`, target `0x9E` | | `0x00448B16` | `music-room-roi-exact-00448b16` | caller bytes/relocations differ | | `0x0044C390` | `player-onupdate` | relocation symbol drift | | `0x0045964D` | `result-screen-roi-exact-0045964d` | caller bytes/relocations differ | | `0x00465CC0` | `anm-manager-unblocked-exact-00465cc0` | relocation symbol drift | | `0x0046F5CB` | `accepted-source-exact-0046f5cb` | object `0x7AC`, target `0x794` | | `0x0046FFC0` | `accepted-source-exact-0046ffc0` | object `0x357`, target `0x34B` | | `0x00470A6C` | `title-screen-roi-exact-00470a6c` | object `0x367`, target `0x369` | | `0x00470E10` | `title-screen-roi-exact-00470e10` | caller bytes/relocations differ | Recheck one without accepting it automatically: ```bash python3 scripts/analysis/verify-exact-units.py \ --unit UNIT --include-unaccepted --json ``` Recover these only as bounded future authored tasks. They do not block the separate target-linked library inventory/provenance work below. ## Next milestone: target-linked libraries The seven previously missing library extents are repaired. The canonical selector now reports no missing-size rows: ```bash python3 scripts/analysis/report-reconstruction-status.py \ --category library --state missing-size --sort address ``` The six D3DX rows were reconciled against the target CPU dispatch tables and the SHA-pinned VC7 PlatformSDK prerelease `D3DX8.LIB` (`0d4a2b642485dcaa7671926a9a1a545c656d5eb73f160fe971b3deebf0b516b5`). Their archive identities are SSE/SSE2 Vec3, Plane, Vec4, and Quaternion normalize members; target body extents stop before archive alignment padding. `operator delete @ 0x004A43CF` is the five-byte VC7 `/MT` `LIBCMT.LIB` `delete.obj` tail jump to `_free`. These boundary/provenance facts now feed the separate accepted library ledger; they are not authored claims. Inventory integrity is now reconciled. Four imported extents were stale and were shortened at target-proven return/next-function boundaries (`0x0049E3CD`, `0x004A51FD`, `_strchr @ 0x004A5BE0`, and `0x004A6890`). The remaining nine overlaps are VC7 CRT nested SEH cleanup funclets and are explicitly represented in `config/mapping-overlaps.csv`; `validate-tracking.py` rejects stale exception rows and reports any new unclassified overlap. Separate library acceptance infrastructure is now in place: - `library-provenance.toml` pins archive identity and SHA-256; - `library-match-units.toml` records target body/compare extents, archive member, COFF symbol, and every relocation target base; - `compare-library.py` verifies archive hash/member identity and replays DIR32/REL32 relocations before comparing the complete target range; - `library-matches.csv` is the independent accepted ledger; - `validate-library.py` is the public CI gate, with `--require-archives` for local hash attestation; `library-progress.py` generates `LIBRARY_PROGRESS.md`. Library acceptance now has **172 / 172 configured units** and **27,280 body bytes** after canonical zero-difference replay. The accepted set contains six SSE/SSE2 D3DX normalize helpers, VC7 `/MT` `operator delete`, seven CRT string/memory helpers (including strict shared-section `strchr`/`strcpy`/`strcat`), six isolated compiler-runtime arithmetic helpers (`_ftol2`, `_chkstk`, `_aulldiv`, `_allmul`, `_ftol`, `_aullshr`), and the `LIBCMT malloc.obj` allocation wrappers `_nh_malloc @ 0x004A423D` / `malloc @ 0x004A4269` with explicit DIR32/REL32 replay, plus the complete currently mapped `heapinit.obj`/`sbheap.obj` core accepted so far: `_heap_init`, `__sbh_heap_init`, `__sbh_find_block`, `__sbh_free_block`, `__sbh_alloc_new_region`, `__sbh_alloc_new_group`, the 735-byte `__sbh_resize_block`, and the 764-byte `__sbh_alloc_block`. The next accepted family also covers eight `trnsctrl.obj` C++ EH helpers, including `_UnwindNestedFrames`, `__CxxFrameHandler`, `_GetRangeOfTrysToCheck`, `_CreateFrameInfo`, `IsExceptionObjectToBeDestroyed`, `_FindAndUnlinkFrame`, `_CallCatchBlock2`, and `_CallSETranslator`. Shared-section `exsup.obj` coverage now also accepts `_global_unwind2`, `_local_unwind2`, `_abnormal_termination`, `_NLG_Notify1`, `_NLG_Notify`, plus the isolated `__EH_prolog`. The EH dependency chain now also accepts `_getptd`, `__InternalCxxFrameHandler`, `_CallSettingFrame@12`, and `_inconsistency`; the latter exposed and fixed a stale 0x26 mapping extent, with `hooks.obj` and target control flow proving the full 0x2D body. `__FrameUnwindToState` is accepted with a 0xAD main-body extent and a 0xCE comparison extent so its compiler-owned cleanup alternate-entry/funclet bytes are replayed without double-counting the separately mapped `0x004AA267` funclet. Auxless whole-section COMDAT support is now explicit/fail-closed, and `FindHandler @ 0x004AA72E` is accepted as a 0x1E2-byte static code COMDAT with a unique offset-zero function owner and 13 replayed REL32 relocations. `tidtable.obj` thread-runtime coverage now also accepts `_mtterm @ 0x004AA049` and `_mtinit @ 0x004AA0D8` with their TLS/lock/calloc relocation graph replayed explicitly. `mlock.obj` coverage now accepts `_mtinitlocks`, `_mtdeletelocks`, `_unlock`, `_mtinitlocknum`, and `_lock`, including the dynamic critical-section table and lazy lock initialization paths. Its immediate dependencies now also accept `_errno`, `_amsg_exit`, and `__crtInitCritSecAndSpinCount`; the latter two required target-proven extent repairs from 0x22 to 0x25 and 0x67 to 0x8B respectively. The message/critical-section leaf layer now additionally accepts `__crtInitCritSecNoSpinCount@8`, `_FF_MSGBANNER`, and `_NMSG_WRITE`; the 0x177-byte message writer replays 30 relocations including CRT string helpers, Win32 I/O, and the security-cookie check. Its immediate code dependencies now also accept `strncpy`, `__crtMessageBoxA`, and the 14-byte `seccook.obj` security-check-cookie helper at `0x004AB43C`; that last row remains conservatively named `FUN_004ab43c` until a repository-wide fastcall-decoration naming rule is fixed. `_report_failure` is now accepted with its full 0x31-byte auxless COMDAT extent, and `_calloc` with its full 0xBB-byte VC7 function-definition extent; `calloc` deliberately retains the legal nested cleanup-funclet overlap rather than truncating the parent epilogue. `trnsctrl.obj` also exposed a missing `CatchGuardHandler @ 0x004A44A1` inventory row and an undersized `TranslatorGuardHandler @ 0x004A44C5`; both auxless COMDATs are now accepted at 0x24/0x71 bytes. `frame.obj` coverage now also accepts `TypeMatch`, the repaired 0x45-byte `__DestructExceptionObject`, `CatchIt`, and `FindHandlerForForeignException`. `_JumpToContinuation` now replays a 0x30-byte COFF section while counting its 0x2B main body, and the linked 0x004A4412 helper is accepted through the existing `CallMemberFunction1` row; archive Function0/1/2 symbols are identical 7-byte COMDAT aliases of that linked copy. `CallCatchBlock` and `BuildCatchObject` are now accepted with 0x97/0x170 body extents while replaying their complete 0x1A7/0x17C auxless COMDAT sections, which include separately mapped EH funclets/tails. Their direct support layer now also accepts `AdjustPointer`, `ValidateRead`, corrected `ValidateWrite`, `ValidateExecute`, and the repaired full 0x33D-byte `memmove`; `FUN_004AA427` is now accepted through the explicit tail-local-funclet schema, pinned to `$L19653` and its `CallCatchBlock` parent section rather than forced through the normal function schema. The same schema now accepts `FUN_004AA267` via `$L19568` at the tail of `__FrameUnwindToState`; `terminate @ 0x004AA9B2` is also repaired from 0x2E to the full 0x35-byte `hooks.obj` function and accepted with two `__getptd` calls plus the final `_abort @ 0x004B05BD` tail jump. The locale/thread pair now accepts `__updatetlocinfo_lk @ 0x004A9F4C`, `__updatetlocinfo @ 0x004AA00E` with a 0x32 body/0x3B comparison extent, and its 9-byte `FUN_004AA040` tail-local cleanup; `_abort @ 0x004B05BD` is also accepted as a 0x17 body with the final `int3` included only in its 0x18-byte comparison extent. This chain now continues through `__freetlocinfo @ 0x004A9E82`; `_abort` dependencies `_exit @ 0x004A6B6A` and `_raise @ 0x004B17F2` are accepted as well, with `_raise` repaired from 0x164 to its full 0x179-byte parent extent while retaining the legal nested 0x004B192D cleanup funclet. The locale teardown chain now also accepts `__free_lc_time @ 0x004AFA38`, `__free_lconv_num @ 0x004AFBC8`, and `__free_lconv_mon @ 0x004AFC27`, closing the direct heap-release dependencies of `__freetlocinfo`. Signal/ctype coverage accepts static `siglookup @ 0x004B17C4` and the `isdigit/isxdigit/isspace` leaf family. Do **not** accept `signal @ 0x004B196B`: `winsig.obj::_signal` has a 0x1A9-byte function-definition section, but replay at that target start has hundreds of non-relocation byte differences; the current row remains an unresolved inventory/provenance item rather than an exact claim. Time/locale formatting coverage accepts `_Strftime_mt`, `_Strftime`, `strftime`, `localtime`, and `time`; the archive-proven VC7 symbol corrects the imported `_time32` mapping name to `_time`. Formatting/small-CRT coverage also accepts `vsprintf`, `sprintf`, `sscanf`, `atol`, `rand`, and `purecall` from their pinned `LIBCMT` members; the stdio wrappers replay their `__output`/`__flsbuf` or `strlen`/`__input` relocations explicitly rather than masking them. Time-runtime dependencies now also accept `__tzset`, `_isindst`, and `gmtime`; termination coverage accepts `_onexit_lk`, `_onexit`, its separately mapped 6-byte tail cleanup funclet, and `atexit`. The internal timezone lane now also accepts `_tzset_lk` and `_isindst_lk` as auxless static `tzset.obj` COMDATs, replaying 58 and 30 relocations respectively; `_isindst_lk` exposes `_cvtdate @ 0x004AADC8` as the next direct dependency. That dependency is now accepted as the full 0x1B8-byte static `_cvtdate` COMDAT; `_tzset_lk` also closes through exact `_getenv_lk @ 0x004B05D5`. The environment conversion chain now continues through exact `_mbsnbicoll @ 0x004B1FC8` and archive-proven `__wtomb_environ @ 0x004B2016`, each with four explicit relocations. String/heap support now accepts the repaired 0x88-byte `strcmp` plus `_msize` as a 0x6A main body with a 0x76 comparison extent and a separately accepted 9-byte cleanup tail. Startup/termination coverage now also accepts `__crtExitProcess`, `_lockexit`, `_unlockexit`, `_cinit`, `doexit`, public `exit`, `_cexit`, and the previously missing `_c_exit @ 0x004A6B8A`; `__crtExitProcess` counts 0x2F body bytes while replaying the final `int3` in its 0x30-byte COFF extent. `initsect.obj` coverage now repairs `_RTC_Initialize @ 0x004ACBFE` from 0x3D to 0x44 and adds the previously missing `_RTC_Terminate @ 0x004ACC42`, both exact 0x44-byte SEH iterator functions. File-I/O wrapper coverage now repairs `_lseek`, `_write`, and `_read` from imported 0xA0 extents to their full 0xAB VC7 function-definition extents. Each parent still contains a separately mapped nested cleanup funclet, but control flow resumes in the parent afterward; the overlap exceptions remain valid and the child does not define the parent boundary. Stdio support also accepts `write_char`, `write_multi_char`, `write_string`, `input::__inc`, and archive-proven `_ungetc_lk`; the latter replaces the imported `FID_conflict:_ungetc` label after exact `ungetc.obj` replay. File-handle support now also accepts `_lseek_lk`, `_write_lk`, `_read_lk`, `_lock_fhandle`, and `_unlock_fhandle`, closing the direct lock/worker dependencies of the repaired `_lseek/_write/_read` wrappers. Error/handle support now also accepts `_doserrno`, `_dosmaperr`, and `_get_osfhandle`, replacing the anonymous doserrno row with its archive-proven identity. Stdio/MBC conversion coverage now also accepts `_getbuf`, `_filbuf`, `wctomb`, `mbtowc`, `__wctomb_mt`, and `__mbtowc_mt`, closing the direct buffer and multibyte conversion dependencies of the accepted `output`/`input` code. Continue pinning provenance/match units for remaining VC7 CRT/runtime, standard-library, D3DX, and compiler-runtime inventory; keep library progress separate from authored totals. Keep authored `implemented.csv`, `matches.csv`, and authored percentages unchanged. There is intentionally no whole-library scanner until archive identity, relocation policy, COMDAT/padding rules, and failure modes are encoded. ## Later whole-executable lane After target-linked library objects are reproducible, audit linker order and padding, globals and static initialization, imports, PE headers, resources, and non-code data. The normal executable currently proves that the reconstructed source links; it is not a claim that the complete PE matches. Use `docs/TOOLS.md` to choose commands. Keep `.analysis/` disposable and update this file whenever the active milestone or a durable blocker changes.