sots-re/campaign/research/research-completion-abi.md

108 lines
8.3 KiB
Markdown

# 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.