Chased to the bottom instead of stopping. The answer is that there was
nothing to fix, and my bench was lying to me.
Entity::Execute (ENTITY.cpp:556, real engine source [T0]) calls PerformAndWatch
ONLY when the app state is RunningMission/EndingMission or the entity
IsPreRunnable(); otherwise it merely WriteSimulationUpdate()s.
Entity::DefaultFlags is DynamicFlag|MasterInstance -- no PreRunFlag. Only
Player and Director add it, and Mech::Reset sets it for a reset MASTER ("a
reset master must tick"). A REPLICANT mech never gets it.
So a peer mech performs ZERO subsystem ticks until the round actually starts,
however much correctly-replicated data is arriving. Measured on the observer:
235 [perf-first] mech 3:161 master <- own mech, immediately
402 [torso-rec-rx] <- peer torso records arriving
2754 [perf-first] mech 2:55 REPLICANT <- peer's FIRST performance
2758 [torso] PushTwist COPY <- its torso ticks 4 lines later
2761 [ent-exec] state=5 <- RunningMission
The peer starts performing exactly at the RunningMission transition. That is
the engine doing what it says.
WHICH MEANS THE PREFIX WAS A BENCH ARTIFACT. BT_AUTOFIRE starts shooting
immediately, during WaitingForLaunch -- something no player can do in a real
match -- so those 60 leading salvos measured a peer whose torso had never run.
Every "ZZZZ...XXXX" pattern in this investigation was that, and the first X
lands within a few lines of the state transition. #141's fix is unaffected and
remains verified: the segment-cache defect was real and mid-match.
Chain of things ruled out on the way, all measured:
* record CADENCE is authentic -- sends on RATE CHANGE (payloads are the sweep
extremes, rate flips sign), peer dead-reckons between them. 12 records for
12 reversals is correct, not starved. My "only 13 records" premise was wrong.
* ComputeTargetTwist clamp -- limits load fine on the copy (+/-2.44346).
* the torso's own executable flag -- restoring the engine's instance branch
(f36f013) is a genuine fidelity fix but moved this by nothing.
* the replicant entity IS offered to the performer, executable=1, from line
171 -- 2500 lines before its first PerformAndWatch. The gate was inside
Execute, not the scheduler.
Adds [perf-first]: a ONE-SHOT per-mech receipt naming entity ID + instance at a
mech's first performance. Every other per-frame receipt in mech4 is anonymous,
which is precisely why this took so long in a 2-node log -- master and replicant
lines were indistinguishable. Name the mech.
Gotcha #29 records the bench-design rule this cost: judge a 2-node bench by
PREFIX vs INTERLEAVED, never by raw percentage, and check [ent-exec] state=
before suspecting replication. missileframe.sh carries the same warning.
#148 to be closed as not-a-bug.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC