night13: close #148 as not-a-bug on the tracker
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018SgmXGNMXavXiafKXf9MDC
This commit is contained in:
co-authored by
Claude Opus 5
parent
cacca58836
commit
43777569f9
@@ -0,0 +1,81 @@
|
||||
"""Night 13: close #148 as not-a-bug with the measured chain. ASCII only."""
|
||||
import sys
|
||||
sys.path.insert(0, r"C:\git\bt411\scratchpad\night7")
|
||||
import gitea
|
||||
|
||||
BODY = """**NOT A BUG -- closing (2026-08-08).** There was nothing to fix here. The bench was lying,
|
||||
and this ticket's own premise was wrong twice over.
|
||||
|
||||
## The answer
|
||||
|
||||
`Entity::Execute` (`ENTITY.cpp:556`, real engine source [T0]) calls `PerformAndWatch` **only** when
|
||||
|
||||
```cpp
|
||||
application->GetApplicationState() == Application::RunningMission
|
||||
|| application->GetApplicationState() == Application::EndingMission
|
||||
|| IsPreRunnable()
|
||||
```
|
||||
|
||||
and otherwise merely `WriteSimulationUpdate()`s. `Entity::DefaultFlags` is
|
||||
`DynamicFlag|MasterInstance` -- **no `PreRunFlag`**. Only `Player` and `Director` add it in their
|
||||
DefaultFlags, 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, no matter how
|
||||
much correctly-replicated data is arriving for it. Measured on the observer node:
|
||||
|
||||
```
|
||||
235 [perf-first] mech 3:161 master <- own mech, immediately
|
||||
402 [torso-rec-rx] <- peer's torso records start 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 it does.
|
||||
|
||||
## So the symptom was a BENCH ARTIFACT
|
||||
|
||||
`BT_AUTOFIRE` starts shooting immediately, during `WaitingForLaunch` -- something no player can do
|
||||
in a real match. Those leading salvos measured a peer whose torso, gait and subsystems had never
|
||||
run. Every `ZZZZ...XXXX` prefix in this investigation was that, and the first `X` lands within a
|
||||
few lines of the state transition.
|
||||
|
||||
**#141 is unaffected and stays fixed** -- its segment-cache defect was real and mid-match.
|
||||
|
||||
## Ruled out along the way (all measured, all recorded so nobody repeats them)
|
||||
|
||||
* **The record cadence is authentic.** My "only 13 records in 5 minutes" premise was wrong. The
|
||||
payloads are the sweep EXTREMES with `rate` flipping sign at each one -- the master sends on
|
||||
**rate change** and the peer dead-reckons `atUpd + rate * elapsed` between them. 12 records for
|
||||
12 direction reversals is correct, not starved.
|
||||
* **The `ComputeTargetTwist` clamp.** The copy's limits load correctly (`limL=2.44346
|
||||
limR=-2.44346 enab=1`), so `Min/Max` was not pinning `targetTwist` to zero.
|
||||
* **The torso's own executable flag.** `Entity::Perform` picks its predicate by instance
|
||||
(`IsNonReplicantExecutable` vs `IsReplicantExecutable`, differing on
|
||||
`|| lastUpdate >= lastPerformance`), and Mech's tick loop had dropped that branch. Restoring it
|
||||
(`f36f013`) is a genuine fidelity fix and is kept -- but it moved this bug by nothing.
|
||||
* **The scheduler.** The replicant entity IS offered to the performer with `executable=1` from
|
||||
line 171, ~2500 lines before its first `PerformAndWatch`. The gate was inside `Execute`, not in
|
||||
who gets offered.
|
||||
|
||||
## What came out of it
|
||||
|
||||
* `[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 exactly why this took
|
||||
so long to see in a 2-node log.
|
||||
* `[torso-copy]` now prints `limL/limR/enab`; `[launchframe]` prints the shooter's live torso twist.
|
||||
* **Gotcha #29** in `context/reconstruction-gotchas.md`: judge a 2-node bench by PREFIX vs
|
||||
INTERLEAVED, never by raw percentage; check `[ent-exec] state=` before suspecting replication.
|
||||
`missileframe.sh` carries the same warning inline.
|
||||
|
||||
## Still worth checking separately
|
||||
|
||||
`#37` (MadCat torso BACKWARDS) and `#70` (torso twist stops after respawn) were flagged here as
|
||||
possibly sharing a cause. They do **not** share this one -- it is not a defect. They should be
|
||||
re-tested against the #141 segment-cache fix instead, which is a real mid-match change."""
|
||||
|
||||
gitea.comment(148, BODY)
|
||||
gitea.call("/issues/148", method="PATCH", payload={"state": "closed"})
|
||||
print("closed #148")
|
||||
Reference in New Issue
Block a user