Files
Cesarus85--ringfall-mjolnir-vr/docs/shape_transfer_executor_strategy.md
T

184 lines
9.8 KiB
Markdown

# Exact-shape transfer candidate executor
## Scope and invariants
This branch productionizes only candidate generation and review-packet emission.
The executor is deliberately unable to apply a patch, invoke a compiler, update a
matching ledger, edit configuration, commit, merge, or integrate.
The repository is read-only from the executor's point of view. Output must be a
new directory outside the repository. A successful run emits an unapplied patch,
a standalone candidate fragment, and review metadata. A refusal emits no
candidate.
The input atlas is evidence to recheck, not an authority for text replacement.
The executor derives the ordered substitution events from the donor and
recipient January target COFF relocations and requires the atlas events to match
exactly. It refuses:
- unsafe or incomplete proof records;
- stubs with a meaningful size of 16 bytes or less;
- unequal padded/meaningful sizes, normalized bytes, relocation count/order/type,
storage class, or prologue;
- non-injective substitutions;
- relocation addend changes, non-symbol substitutions, and constant symbols;
- donor source that is missing, ambiguous, recursive, or not a real definition;
- missing, ambiguous, or incompatible recipient prototypes/inline definitions,
including return type and every parameter type;
- stale/wrong-callee atlas events;
- a transformed symbol that is not present exactly as often as the donor target
relocates it;
- missing recipient declarations unless a single unambiguous declaration can be
copied verbatim from a repository header (the packet pins that header hash);
an optional manifest can pin the same operation explicitly; and
- a recipient function already defined in source.
Text generation is token substitution only. It changes the donor function name
and the relocation-proven symbol identifiers; it cannot synthesize a body,
change constants, reorder statements, or retry a refusal with heuristics.
## Acceptance boundary
`CANDIDATE_GENERATED_NOT_ACCEPTED` is the strongest possible executor result.
Exact acceptance remains exclusively:
1. the hardened cross-name `tools.coff_compare.section_infos_equal` comparison;
2. a zero-regression whole-translation-unit manifest comparison; and
3. unchanged whole-object data/BSS/ownership fingerprints.
Those gates must be run in a disposable build worktree by a human review lane.
The executor neither runs them nor converts their future results into matching
credit.
## Operator usage
Invoke the tool from a clean campaign worktree. `--target-root` is the directory
whose children mirror the atlas unit names and contain the January target
objects. `--output-dir` must be a new directory outside the repository.
```powershell
python tools\transfer_executor.py `
--repo-root C:\path\to\campaign-worktree `
--atlas C:\path\to\transfer_atlas_v2.json `
--target-root C:\path\to\build\split `
--base-root C:\path\to\untouched\build\base `
--recipient-unit source/objects/widgets/flags `
--recipient-function _flag_delete `
--donor-unit source/objects/widgets/antenna `
--donor-function _antenna_delete `
--output-dir C:\path\outside\repo\flag-delete-review
```
The donor selector is optional only when the recipient selector is unique. The
tool refuses an ambiguous selection. Missing declarations are copied only when
one exact declaration exists in repository headers. An operator may instead
pass `--declaration-manifest`; each entry must include `symbol`, verbatim `text`,
repository-relative header `source`, and the SHA-256 of that header. Extra,
stale, non-verbatim, or non-header declarations are refused.
A successful output directory contains:
- `candidate.c`: standalone generated fragment;
- `candidate.patch`: unapplied unified diff;
- `review_packet.json`: hash-pinned inputs, derived events, generation checks,
and all acceptance gates marked `NOT_RUN_REQUIRED`;
- `frozen_tu_baseline.json`: the complete untouched recipient target/base
function, symbol, non-code section, and ownership fingerprints plus the
pre-edit strict-exact sibling set; and
- `REVIEW.md`: human handoff and mandatory gate list.
## Implementation and validation log
- 2026-07-29: observed the clean canonical campaign integration HEAD at
`5b61655c5e40f6964d8dd37d2db4364b0a82c07e`.
- 2026-07-29: created isolated branch `codex/shape-transfer-executor` and
worktree `work/shape-transfer-executor` from that commit.
- 2026-07-29: reviewed the fail-closed executor spec, minimum transformation
language, duplicate atlas, donor/recipient map, 12-case experiment driver,
atlas generator, and later production blueprint.
- 2026-07-29: synthetic executor suite passed 22/22. The lexically first test
was the requested zero-substitution, non-rasterizer class. Covered successful
no-substitution and callee/data substitutions; unchanged constant
relocations; explicit and automatic hash-pinned declarations; immutable and
atomic packet emission; frozen pre-edit TU/object manifests; changed-input
detection; review lints for donor-domain parameter names and potentially
redundant generated declarations; and refusals for wrong callees/stale atlas
events, non-injective maps, relocation/statement-order changes, stubs,
ambiguous sources/pairs, missing declarations/baselines/prototypes,
incompatible return/parameter ABIs, pre-existing recipient bodies, and
source/target occurrence mismatches.
- 2026-07-29: the complete `tools/test_*.py` suite passed 167/167.
## Archived-artifact validation
Validation used `transfer_atlas_v2.json` and the archived January target objects
under `fable-transfer-exp/build/split`. Generation read source only from this
clean `5b61655c5` worktree.
The real zero-substitution non-rasterizer pair was tested first:
- `ai/actions:_set_real_vector3d <- ai/ai_debug:_set_real_point3d`:
**REFUSED (`donor-source-missing`)**. The older
`donor_source_resolved` flag was a regex false-positive: `ai_debug.c`
references `set_real_point3d` but does not define it. The implementation is
inline in another header. Header-emission donor resolution is intentionally a
later resolver upgrade, not a heuristic in this executor.
The five previously exact experiment pairs then produced:
| Recipient | Result | Detail |
|---|---|---|
| `objects/widgets/flags:_flag_delete` | `CANDIDATE_GENERATED_NOT_ACCEPTED` | Ordered target relocations derived `_antenna_data -> _flag_data`; unique `datum_delete` prototype copied verbatim from `source/memory/data.h` and header hash pinned. |
| `ai/ai:_ai_dispose` | REFUSED | No explicit `ai_debug_dispose` declaration in recipient context or a unique repository header. |
| `effects/effects:_effects_dispose` | REFUSED | No explicit `effect_data` declaration/definition in recipient context or a unique repository header. |
| `objects/object_lights:_code_00129100` | REFUSED | No explicit `light_cluster_partition` declaration/definition in recipient context or a unique repository header. |
| `objects/object_lights:_code_00129120` | REFUSED | Same missing `light_cluster_partition` evidence. |
All four missing-declaration refusals occurred after the target-object structural
and relocation-derived substitution checks passed. The executor did not recreate
the experiment driver's hand-written declarations because the production
blueprint requires real-header provenance.
Independent human review of the first `flag_delete` packet made two source-only
cleanups that relocation evidence cannot prove: `antenna_index` became
`flag_index`, and the redundant local `datum_delete` prototype was removed.
After that cleanup the candidate passed strict comparison at 32/32 bytes and
2/2 relocations; all four pre-existing strict-exact siblings remained exact;
both existing `.rdata` COMDAT payloads/sizes remained byte-identical; and
`_flag_data` remained the same 4-byte COMMON symbol. This is a valid
zero-regression transfer validation, not production admission: `flags.obj`
remains incomplete at 5/16 functions, no production source was changed here,
and no matching credit was granted. The executor now emits explicit
`REVIEW_REQUIRED` lints for both classes of cleanup instead of attempting them.
An early next-packet attempt for
`effects/contrails:_local_random_range <-
camera/bored_camera:_real_local_random_range` exposed a serious false-positive
class and is **revoked**. Relocations suggested only
`_real_seed_random_range -> _seed_random_range`, but the donor is
`float(float, float)` while `source/math/real_math.h` already defines the
recipient inline as `short(short, short)`. Their wrapper bytes happen to share a
shape because both argument types consume dword stack slots and each
tail-returns its own callee's native ABI. Applying the packet in an isolated
review worktree failed CL with C2371 at `contrails.c(162)`, pointing to the
conflicting inline definition at `real_math.h(1344)`.
The executor now requires a unique compatible recipient declaration or inline
definition from the actual recipient include closure, with identical canonical
return and parameter types, before source transformation. Missing, ambiguous,
function-pointer/array-unsupported, or incompatible evidence is terminal. A
synthetic regression test reproduces the real/short conflict, and the real pair
now refuses as `recipient-prototype-incompatible` without creating output.
Re-scanning all 21 atlas entries marked `donor_source_resolved` under this
hardened rule produced zero new candidates. Therefore the current automated
candidate batch is empty. The independently validated `flag_delete` transfer is
the sole human-reviewed result, but it is still not admitted and the hardened
generator would now refuse it until a recipient prototype is sourced. The other
proven experiment pairs and the zero-substitution pair stay closed until
declaration, prototype, or donor-source provenance is improved without
heuristics.
No production source, matching status, configuration, or ledger changed during
artifact validation.