"""Night 13: close #137 (not a bug) and file the desktop throttle-latch follow-up. ASCII only.""" import sys sys.path.insert(0, r"C:\git\bt411\scratchpad\night7") import gitea BODY_137 = """**NOT A BUG -- closing (2026-08-08).** The reset is correct on both sides. The heat is real, and the mech earned it: it respawns still under power. ## What the field log actually shows From Sauron's match log (`steam_20260806_c_michael_XIAOLONG.log`), the respawn at line 39450: ``` 39450 [respawn] Mech::Reset 3:30 healed+moved to (...) alive=1 zones=21 subsys=33 [techstat] SLaser_1 / LLaser_1 / HUD / Gyroscope / Avionics / GeneratorA / HeatSink ... condition CLEARED <- every live condition clears [techstat] Myomers condition 3 SET <- Overheating, immediately [mppr] in thr=1 pre=1 -> ... [gaitSM] cycleSpeed=14.6 legCycle=14.6 state=12 <- already RUNNING [techstat] Condenser5 condition 3 SET <- "dumping into coolant loop 5" 39519 [techstat] GeneratorD condition 3 SET <- Sauron's generator D ``` `[rstat]` fires about once per second (98 frames @ 10.2ms), and the reset plus the myomers trip sit inside one rstat block -- so myomers overheat in well under a second, generator D in one to two. The reset itself is clean: **every** live condition CLEARs 12-16 lines after each `Mech::Reset`, at every respawn in the log. The synthetic bench agrees -- every roster subsystem, including all six Condensers, reads `T=77 start=77` at the reset. ## Why it looked like maxed heat **`condition 3` is an operating flag, not an alarm.** Census over the whole match: | subsystem | cond 3 SET | CLEARED | |---|---|---| | LLaser_2 | 33 | 33 | | LLaser_1 | 31 | 31 | | SRM4 | 26 | 26 | | PPC_2 | 18 | 18 | | GeneratorD | 5 | 4 | | Myomers | 5 | 4 | | Condenser5 | 1 | 1 | Every weapon trips Overheating on each volley and clears it on cooldown. **Every subsystem is balanced** -- the odd extra SET is only the log ending mid-heat. Nothing latches, nothing sticks. `condition 6` (BadPower) behaves the same way (Myomers 8/8, PPC_1 3/3, MLaser_1 3/3) as the bus browns out under simultaneous draw. GeneratorD's longest continuous overheat came out normally. So the post-respawn SET is the mech *operating*, not a failed reset. ## Why the heat arrives instantly The mech comes back **at whatever throttle the pilot left**: `thr=1`, `cycleSpeed=14.6`, gait state 12 at the instant of reset. `Mech::Reset`'s subsystem loop starts at **index 2**, and the ControlsMapper is **index 0** -- so the throttle is never reset. **The binary does exactly the same.** That is correct for a pod: the throttle is a physical lever still under the pilot's hand. Respawning under power is authentic behaviour. Oracle's read that the myomer heat rate "felt right" was correct, and matches the data. ## Ruled out along the way `Mech::Reset` dispatch, the full subsystem RTIS chain (Generator `@004b215c` is an instruction-for-instruction match; HeatSink `@004ad760` faithful; every RTIS class has a DeathReset), stale coolant-loop links (`linkedSinks` is written only in the streaming ctor and cannot drift), and the valve fractions (`BTRecomputeCondenserValves == @0049f788`). ## Follow-up The one genuine defect found is a desktop-only input issue, filed separately -- see the throttle latch ticket. It does not affect the pod. Knowledge base updated so this is not re-chased: `context/decomp-reference.md` §TechStatus (the routine/self-clearing semantics + this post-mortem) and `context/gauges-hud.md`.""" TITLE_NEW = "Desktop/Steam: virtual throttle lever survives death -- you respawn already running" BODY_NEW = """Split out of #137, which was closed as not-a-bug. The heat model and the reset are both correct; this is a port-layer input issue and it affects **desktop/Steam only, never the pod**. ## The defect On the pod the throttle is a physical lever. Respawning under power is authentic -- the pilot's hand is on it, they can see and feel where it is, and `Mech::Reset` deliberately does not touch it (the subsystem loop starts at index 2; the ControlsMapper is index 0). The binary behaves the same way. The desktop glass bridge emulates that lever with a **file-static ramp accumulator**: * `sLever` -- `static float sLever = 0.0f;` (`game/reconstructed/mech4.cpp:3250`) * published each frame as `gBTDrive.throttle = sLever` (mech4.cpp:3892/3897) * consumed as `key_throttle` -> `throttlePosition` (mechmppr.cpp:677, :780) The only things that zero `sLever` are the **X-button all-stop** (mech4.cpp:3754) and a direction-crossing snap (:3842). **Nothing on death or respawn touches it.** So a pad/keyboard pilot who dies at speed respawns at speed -- while physically holding nothing, and with the lever position invisible to them. The pod's authenticity argument does not cover this case: there is no lever to feel, and a gamepad stick self-centers, so the input affordance actively contradicts the latched state. Observed consequence in the field (Sauron's log, the #137 evidence): the mech leaves the drop zone at `thr=1` / `cycleSpeed=14.6` the instant it spawns, and the myomers, Condenser5 and GeneratorD all trip Overheating within one to two seconds. Reads to the player as "respawned with heat maxed". Note this is **not** the same as the Thrustmaster/RIO path, which is already correct: `MechThrustmasterMapper::InterpretControls` (`@004d2150`) recomputes `throttlePosition` from scratch every frame off the live `throttleForward`/`throttleReverse` states, and `throttleForward` is databound (written by the input layer each frame). Only the desktop `sLever` accumulator latches. ## Suggested fix Zero `sLever` (and the detent) on respawn in the desktop bridge only -- the same treatment the X all-stop already applies -- so a desktop pilot comes back stopped. Gate it so pod builds keep the authentic physical-lever behaviour. This is a gameplay-behaviour decision as much as a bug fix: it changes whether desktop players respawn moving or stopped. Worth a call before it ships. ## Not yet done Not fixed, not benched. Filed from a static read of the input path plus the field log.""" gitea.close(137, BODY_137) num = gitea.create(TITLE_NEW, BODY_NEW) print("closed 137; created:", num)