# Authored mission and campaign fidelity

This pass extends the four complete recorded-demo comparisons to authored mission
starts and consecutive career returns. Expected states come from original
instructions; the native game receives only launch files, initial random state,
frame ratios and controlled return inputs. No expected actor, counter, random
state or result is assigned to the native simulation.

## Corrected mission behavior

### Starting damage and controller order

DBSIM 0x1e638 constructs one HERC, enters its initial deciding controller
(0x117bb / 0xfdfc), then applies authored starting damage (0x12f20), before
constructing the next actor. A damage transition can enter the disabled
controller through 0x136ac / 0xfdfc. Every controller entry advances the shared
stagger by 13, so batching all initial entries before damage changes subsequent
actors' decision timing.

Starting damage at 0x1eb99 precedes group assignment at 0x1f16e. Individual
destruction counter and trigger actions already apply; group destruction
accounting does not. The native constructor now observes these same boundaries.
Restoring player-roster condition remains the original separate load operation.

### Activation does not suspend every ground-object update

The phase-four fixed-building and turret updaters (0x2df8 / 0x3364) visit all
constructed ground actors, including members of waiting groups. Their animation
and combat updates are distinct from HERC/flyer controller dispatch, which is
gated by group activation. Native ground updates previously applied that gate
too broadly.

Group dispatch retains the separate activation edge: a latched trigger clears
the pointer on that visit but does not also run the controller immediately.
Subsequent phases can see the newly active group.

### Objective references use the compacted source maps

0x1d850 zeroes the source-to-pool lookup arrays at 0xaf818, 0xaf914 and
0xaf97c. Construction fills entries only for instantiated source records.
An objective referencing an uninstantiated source therefore resolves to slot
zero of that actor kind when that pool exists; 0x1cff4 performs the pool lookup.

The native lookup previously treated an absent source entry as no target.
This affected chapter-six escort/rescue missions, including B0_C6_2A's target
grade and B0_C6_4A's ability to launch. The deterministic zero-map behavior is
now retained. It is not a new mission-target selection policy.

## Confirmed original memory defects

These cases are explicitly distinguished from unchanged-executable comparisons.
The authentic implementation uses bounded behavior rather than reproducing
unrelated heap contents.

### Negative formation IDs

Some authored groups have formation -1, while follower placement and movement
still index the formation table. Original helpers 0x1a098 (HERC), 0x1c7f0
(flyer) and 0x441c (ground) do not check that index. The existing nine guarded
probes in work/research/missions/formation-bounds.json show that changing memory
before the allocation changes the resulting coordinates.

Live native sessions now use formation zero for a negative ID. The inspection
catalogue still exposes these positions as undefined by default, preserving its
304 construction-fixture comparisons. This is a chosen deterministic fallback,
not evidence of the author's intended formation.

The authored runtime probe's --repair-formations option changes only negative
arguments at those original helpers, records every replacement, and preserves
the original launch bytes. Comparisons using that option identify repaired cases.

### Deferred effect queues

0x63760 appends a pointer to the queue's signed count, then increments it.
The count occupies offset +80: pointer number 21 overwrites the count itself.
There is no capacity check. Original pools can contain more than 20 objects
(explosions: 40; debris and flat secondary objects: 150; smoke puffs: 200).

B0_C5_70 demonstrates this during ordinary startup effects: frame 9 retires
40 explosions and 40 secondary flat objects. The untouched reference corrupts
the queues. Extending only the flat-object queue exposes a later consequence:
at frame 203 the original explosion pool cannot allocate, so it skips a random
draw that the native, correctly reclaimed pool performs.

The --repair-effect-queues probe stores pending pointers outside those fixed
arrays, then runs the original 0x63784 destructor/free-list collector in FIFO
batches of at most 20 at its normal phase. It preserves pool capacity, allocation
order and random calls. The recorded overflow events identify the affected queue,
frame and count. Native object_pool already uses a dynamic pending vector.

The collector sequence includes lights, explosions, debris, smoke emitters,
smoke puffs, flat secondary objects and projectiles. 0x664c collects emitters
then calls the puff collector at 0x6638; the earlier isolated world probe had
omitted both smoke collections. Its correction is a reference-harness fix,
not a change to native smoke behavior. Historical failed captures remain
available separately from the corrected and explicitly repaired references.

## Consecutive campaign journeys

capture_campaign_journeys.py starts each shell return in a fresh original GO
image. Only the saved career, hangars, registry and handoff files persist.
It supplies controlled grades, damage, salvage, statistics and counter changes,
then executes original return processing, repair, saving, graph advancement and
the next launch. Success and failure paths cover all three battle sets:

| Battle set | Success returns / ending | Failure returns / ending |
|---|---:|---:|
| 0 | 40 / node 99 | 15 / node -1 |
| 1 | 26 / node 99 | 7 / node -1 |
| 2 | 26 / node 99 | 7 / node -1 |

All 121 transactions match native career and hangar bytes, return and next-launch
random states, graph positions, terminal readiness, SCRIPT.DAT, PLAYER.MEC and
MISSION.VAR. Original SCRIPT.DAT stale tails remain outside the last actual
write extent. These are complete persistence/progression journeys with controlled
flight results, not claims of 121 combat victories or manually played campaigns.

### Campaign slots can name random-mission lists

GO 0x140a5 distinguishes a .MSN filename from a BST mission-list filename.
The latter is loaded through 0x201b7 (byte count followed by zero-terminated
names), then 0x20289 consumes one bounded random draw to choose an entry.
ANY_MSN.DAT contains 13 entries, including an intentional repeated SM_ASS01
entry; deduplicating it would change the selection distribution.

The native shell previously attempted to open the list filename as a mission.
It now resolves the list before compilation and preserves the original random
draw and duplicate entries. The consecutive journeys exercise this path after
accumulated campaign returns, which isolated graph-name comparisons did not.

## Completed comparison coverage

| Run | Cases | Consecutive frames per case | Matched frames |
|---|---:|---:|---:|
| Supported authored sources | 75 | 256 | 19,200 |
| Later-career handoffs | 10 | 256 | 2,560 |

All 21,760 world frames match. The authored run includes 375,552 HERC/flyer
states and 176,640 ground-object states. The career run adds 45,312 HERC/flyer
states. Reports are work/research/missions/authored-runtime-final/checks.json and
work/research/missions/campaign-runtime-final/checks.json; full expected states and
per-case comparator transcripts sit beside them.

Seven source cases use the explicitly recorded formation repair: B0_C3_1A,
B0_C3_3A, B0_C3_5A, B0_C6_0A, B0_C6_1A, B0_C6_3A and B0_C6_7A. The C5_70 source
case and two career cases record the explosion/flat-object queue overflow
repairs. No other queue overflow occurred in these runs.

The native regression suite retains a 64-frame consecutive prefix for every
source, all ten 256-frame career runs and all 121 campaign transactions. Its
provenance records the hashes of full original captures and all handoff files.
The complete existing 260 checks and the three new suites pass, 263 in total.
The original full capture outputs remain here, including historical failures
that explain the diagnosed differences.

## Reproduction and limits

From earthsiege-reverse:

~~~sh
.venv/bin/python -B tools/capture_campaign_journeys.py
.venv/bin/python -B tools/check_authored_mission_frames.py --steps 256 --jobs 4 --repair-formations --repair-effect-queues --output work/research/missions/authored-runtime-final
~~~

The authored sweep selects one coherent seed-17 launch per supported source,
preserving groups, activation, sides, objectives and roster. It supplies neutral
player input, fixed frame ratio 256 and a repeatable simulator RNG warm-up of 17.
It compares all HERC/flyer transforms, controllers, damage, power, sensors and
animation; ground damage/animation; target selections; activation triggers;
group cursors; all 100 counters; mission outcomes/clocks; and complete shared RNG.

Later-career inputs under work/research/missions/journey-launches are exact next-launch
files from the transaction journeys, with provenance identifying the return.
They exercise accumulated equipment, damage, repair, history and event counters.
The same checker accepts repeated --launch DIRECTORY arguments for them.

These bounded startup simulations do not replace the four complete recorded
input replays or establish every late combat interaction and campaign branch.
Tiny audio completion/retry timing differences retain their separately documented
boundary; this pass prioritizes mission content and gameplay state.


## Extended player-controlled missions

The [extended validation report](AUTONOMOUS_VALIDATION.md) adds player controls,
longer runs, a second launch seed and sanitizer checks. Six mission comparisons
exposed a missing native player-disable transition, now corrected. Two others
exposed an unwritten original aim-component field; a third exposed an arithmetic
overflow in long obstacle detours. The report separates untouched original
captures from the explicitly corrected references and records both repairs.
