2.4 KiB
§403
An undo-journal that restores by NAME corrupts any file whose symbol is declared twice — and reports success.
Both fix_arity_callers --undo-journal and cast_self_callers --undo-journal record the original text of
each edit and restore it keyed by function name. When a symbol has more than one declaration in the file,
the originals are restored into the wrong occurrences, silently swapping distinct prototypes.
Byte-witnessed twice in one session (P31 S70):
fix_arity_callersprintedrestored 382, kept 0, missing 0;git diffshowed 97 insertions / 97 deletions in the FLEET-SHAREDsrc/shared/engine_core.h—func_8012A828()<->(int a0, void *a1)<->(s32 a0, void *a1)rotated between three declaration sites.cast_self_callersprintedreverted 10 edit(s) across 1 file(s);src/800.cwas left with the two declarations offunc_80031988swapped ((Ent30D80 *arg0)<->(struct Ent30D80 *)).
This is R48 (never key by bare function name) applied to a journal, and R57 (an instrument's own write path is part of the instrument). The byte-gate does not necessarily catch it: the corruption is in a header, and a rebuild only differs if some binary's codegen happens to depend on the swapped prototype.
Rules. A journal records file + occurrence index (or byte offset), never just a name; and an undo
hash-verifies the restored file against the recorded pre-edit content and FAILS LOUD on mismatch.
After ANY undo-journal, run git diff on the touched files and restore the specific named file from
HEAD if it is not clean — never a blanket git checkout -- src/ (R42).
SHIPPED (S70). The occurrence->original mapping is not recoverable from either journal format,
so both tools now REFUSE (rc=2) when one (file, after) group maps back to differing before
texts — naming the file and the rival originals, and writing nothing. Journals additionally record
per-file sha_before, and a clean undo hash-verifies its own result. Negative-controlled against the
journal that caused the corruption: it refuses and leaves the tree untouched. The refusal also showed
why guessing was hopeless — extern void func_8012A828(); maps back to four distinct originals
((int a0, void *a1), (int, void *), (s32 *, s32), (s32 *a0, s32 a1)). A loud refusal costs
one git checkout; a silent swap costs a corrupted fleet-shared header nobody notices.