# Completion record ABI recovery Static handoff only. The provenance index is `verify/results/research-completion-abi/reva-2026-09-09-index.md`; the regenerated instruction capture and interpretation are respectively `verify/results/research-completion-abi/objdump-2026-09-09-ownership.txt` and `verify/results/research-completion-abi/recovered-static.md`. The complete dedup/helper repair is `verify/results/research-completion-abi/objdump-2026-09-09-dedup-helper.txt`; its first-window raw provenance is superseded by the paired captures and identity record in `verify/results/research-completion-abi/objdump-2026-09-10-boundary-repair.md` under Astra decision `d-d2a9b8be6399a6abaa0e05a5`. Input identity is `dumps/sots.exe`, SHA-256 `970b7de729956a53094c7eb98aba4270aee98e2fed5daf0d39e290013c90c841` / MD5 `9969481c39f4b33a8a21c48b62abee4c`. The ownership archive's terminal-byte provenance is likewise superseded by the complete package `verify/results/research-completion-abi/run-79357a65226f61d6a86c042d/` under Astra decision `d-d4c494ba02ada278030ef473`. Its six narrow/wide pairs, raw section-byte checks and full ten-window audit establish the encoded return immediates while preserving the static-only limitation. The package found three additional truncated historical stops (ObservedTech append/reallocator and string allocation/replacement); their widened streams are now the byte authority. No archive production-history inference or live-safety claim is made. The TurnEvents correction's historical-session boundary authority is `verify/results/research-completion-abi/run-9daf5c3b75547271d5c3b4ed/`. It superseded the stale-session attribution and truncated nested-copy stream invalidated by decisions `d-fd5aff1eaf78a8c15d96723c` and `d-0bb927e63b915c87a58d4257`. The package binds the actual session and a fail-if-used output directory; captures complete helper authority through `0x0077992f`; and retains `0x00779a20` as an expected-failing boundary beside complete `0x00779a21`, `0x00779a23`, and `0x00779a28` controls plus raw bytes. It is analyst static evidence awaiting a fresh independent verifier, not restored acceptance. Astra decision `d-e9d6d48cd77538556d1a1c1f` later barred reuse of that package against changed source. The current-source remeasurement is `verify/results/research-completion-abi/run-35e59053176da458d8b46fea-repair1/`, with preflight, plan, recipe and interpretation in the sibling `run-35e59053176da458d8b46fea-preflight.json`, `plan-run-35e59053176da458d8b46fea.md`, `capture_run_35e59053176da458d8b46fea.py`, and `report-run-35e59053176da458d8b46fea.md`. The unsuffixed run directory preserves a failed recipe predicate and is not authority. The new package is analyst static evidence awaiting fresh independent reproduction, not restored acceptance. ## Implementable machine boundaries recovered * `0x008562a0`: ObservedTech default constructor, ECX receiver, EAX return, plain `ret`. * `0x007b7320`: ObservedTech vector append, ECX receiver plus one stack word, `ret 4`; stride `0x2c`. Its copy helper is `0x0079a150` (cdecl-style allocator/destination/source stack arguments), which copy-constructs the embedded string rather than copying a vector element header. Capacity growth is `0x007b5820` -> `0x007b34e0` -> `0x0057e590`. * `0x0057e590` calls `0x00924fb6` with `count * 0x2c`; reallocation destroys every old element via virtual slot 0 with zero and frees the array through `0x00924faa`. These are MSVCR100 scalar-new and scalar-delete import thunks, not clean-room allocator operations. * `0x0086c580`: PlayerEvent vector append, ECX receiver plus one stack word, `ret 4`; stride `0x74`. It grows via `0x00869500` and copy-constructs through `0x007693f0` (ECX destination, stack source, EAX destination return, ret 4), independently assigning all three strings. `0x0061ae90` releases each long string via `0x00924faa` when capacity is `>= 0x10`. * `0x004249a0` (reached by `0x00425430` assignment) allocates through `0x00924fb6` and releases a prior long destination buffer through `0x00924faa`. A temporary long string is therefore not transferable by raw header copy. * `0x00885380`: get-or-create TurnEvents bucket, ECX EventStorage receiver plus stack turn, EAX bucket return, `ret 4`. It returns the last existing matching turn. On absence it initializes the stack bucket's vptr and empty nested-vector header but **not** its `EvTurn`; `0x00884cb0` copies that incoming stack word and deep-copies the nested vector. After temporary nested-vector cleanup, get/create writes the requested turn into the stored last element and returns it. The transient word is not measured randomness or a zero default. Fresh correction capture: `verify/results/research-completion-abi/run-16f8e9b6376b278c4870be09/`, governed by `d-b51f3f76803e852ed250846a`. * `0x00884cb0`: outer TurnEvents vector append, ECX vector receiver plus stack source, `ret 4`, stride `0x18`. Full-capacity growth is `0x008841a0` -> `0x00883a60`; allocation is `0x006e8f50` -> `0x00924fb6` with `count * 0x18`. Existing buckets are copy-constructed by `0x0077fed0`, including an independently allocated/copied nested PlayerEvent vector via `0x00779850` -> `0x0078af40` (`count * 0x74`) -> `0x007725a0` -> `0x007693f0`. * TurnEvents virtual slot zero resolves from vtable `0x00a0f07c` to `0x0062e120`. It destroys the nested vector through `0x00629580`; that destroys every `0x74` PlayerEvent, frees the nested block, and zeros its three pointers. Static unwind edges clean partial PlayerEvent and TurnEvents ranges and free the new outer block, but no allocation failure was executed live. ## Ordering / visible effects RecordObservedTech's append predicate is name absence, not capacity. A matching existing record keeps first-turn/name and updates last-turn/with mask. `0x00825d40` scans a bucket's events in `0x74` steps, checking action, location, three floats, message and image before passing both description strings to `0x0046f8c0`. Fresh paired-boundary instructions establish that helper as caller-cleaned `bool string_not_equal(stored, candidate)`: it returns one for any byte/length difference and zero for equality, handling each operand's inline/heap representation at capacity `0x10`. FindDuplicate reaches the match return only on zero, so `EvDsc` equality is required and a description-only difference does not deduplicate. This statically contradicts the inherited description-omission claim; decision `d-2ff30c9f5355116bea822924` required the now-archived complete branch/helper repair. The later provenance correction does not itself prove these semantics: an independent verifier must reproduce the repaired package and predeclared falsifiers. The wrapper returns the first element equal in all fields and writes nothing. `0x00879eb0` prunes only a leading stale run (`EvTurn < turn-50`), deep-shifts from the run's last stale element, and therefore removes `n-1`: one stale bucket survives, a single stale bucket causes no write, and stale buckets after a fresh bucket are not inspected. The no-duplicate EventStorage path remains distinct from event-vector capacity: it is the path that appends a `0x74` PlayerEvent and changes IDs/vector contents. Caller text/position/action/defaulting and the exact PostEvent write order remain required inputs/effects. No RNG draw occurs in the recovered bucket, duplicate, prune, copy, allocation, or destruction boundaries. ## Original/runtime dependencies and limits Any original-assisted allocation, string assignment or deletion must retain allocator-family compatibility: the recovered calls target the original MSVCR100 import thunks. A standalone replacement needs its own coherent allocation/destruction boundary; calling these original helpers is an original dependency, not independent replacement. Calling `0x0046f8c0` likewise retains an original string-layout/comparison dependency, though its equality behavior is implementable without allocation in a standalone boundary. Required unavailable proof inputs are a safe long-string/full-capacity pre/post fixture (or equivalent archived trace), same-bucket equal/description-only-different event fixtures covering short and long strings, exact exceptional cleanup outcomes under a live throw, and independent reproduction of the named static windows and falsifiers. This handoff makes no live allocator-safety, runtime event-construction, or replacement-acceptance claim.