diff --git a/context/decomp-reference.md b/context/decomp-reference.md index 33bc39a..09e57b0 100644 --- a/context/decomp-reference.md +++ b/context/decomp-reference.md @@ -796,6 +796,10 @@ default-ON (`'0'` disables). | `BT_INCOMING_LOG` | `[incoming]` missile-alarm receipt (#83): LOCK/clear edges + ~1Hz held lines with distance (mech4.cpp PerformAndWatch latch) | | `BT_DESIGNATE=enemy` | bench designator (#83 rig): stamps the production target slots (+0x388/+0x37c/+0x38c) with the nearest live mech on frames where the boresight pick found no mech — standoff locks; a real pick still wins; HUD ring untouched | | `BT_WORLDHIT=0` | disables the missile flight sweep's static-solid-tree half (#175) — restores the heightfield-only world test (A/B lever; default on) | +| `BT_KEYSIM="rate:sec,..."` | scripted key-hold schedule (#102 bench): overrides `gBTInput.leverRate` segment by segment so a headless bench drives the REAL lever integrator + zero detent + gait SM (the forcedThrottle harnesses bypass the lever); after the last segment the lever rests (mech4.cpp, after BTInputPoll) | +| `BT_KEYSIM_REV="t:dur"` | hold the pod's REVERSE button (0x3F) in [t,t+dur) on the BT_KEYSIM clock — drives `gBTReverseHeld`, the chokepoint every rig funnels through (the authentic sign-flip shape) | +| `BT_KEYSIM_TURN="t:dur"` | full-right turn pulse in [t,t+dur) on the same clock (the #102 twist-rescue leg) | +| (receipt) `[brake]` | hard-brake slew engage/release under BT_GAIT_TRACE (#102: forward cycle + negative demand → forwardCycleRate=superStopAcceleration + gyro lurch/judder; mech4.cpp drive block) | | `BT_CRIT_PROBE=` | hammer one own-mech zone every 4s (crit-propagation diag, task #2; mech4.cpp) | | `BT_REPL_LOG` | replicant/MP replication log (mech4.cpp) | | `BT_GOTO="enemy"\|"x z"` / `BT_GOTO_LOG` | self-driving beeline (to the enemy or a map coordinate) + its log | diff --git a/context/locomotion.md b/context/locomotion.md index 922d09a..4a15f4d 100644 --- a/context/locomotion.md +++ b/context/locomotion.md @@ -31,7 +31,8 @@ to a steady pose that the cycle clips never rebind, so it HOLDS.) Decoded from B `[hip]` probe [T2]: - `swr` ramps `jointhip` 0 → **−8°** (stand→walk), `wrl/wrr` −8 → **−11.1°** (walk→run), `wsl/wsr` −8 → 0 (walk→stand). The dedicated return clip only exists because the lean - persists. The BLH has NO `jointhip` channel in any clip → it stays level (both views). + persists. The BLH **and the OWENS** have NO `jointhip` channel in any locomotion clip → they + stay level (both views; Owens jc=9 = root + 8 leg hinges, #102 content audit 2026-08-14 [T1]). - **Two clip sets per mech.** The ctor gate (@part_012.c:10308-10320) binds the **INTERIOR** set (4-char `'i'` suffix, `LoadLocomotionClipsExt` @004a86c8) to the **local cockpit master** — those clips animate `jointshakey` (cockpit shake, a BALL joint) and OMIT `jointhip`, so the PILOT's own @@ -129,6 +130,59 @@ Port: keyboard lever snaps out of the band at rest (mech4.cpp "GAIT DETENT" acco the glass PadRIO throttle slew applies the SAME at-rest snap (L4PADRIO.cpp, band published in lever units via the mech4.cpp `gBTGaitDetentLo/Hi` seam — 2026-07-20 glass re-test) [T2]. +**REVERSE is a BUTTON, never a lever sweep (2026-08-14, #102 audit) [T1]:** the pod's throttle +lever is 0..800 ADC → [0,1] forward-only; reverse = HOLD the red button on the throttle handle +(RIO unit 0x3F `Throttle1`, keyboard LALT; manual p7 "hold in the red button while +accelerating"). The mapper formula (@004afd10, part_013.c:7318-23) is a flag sign-flip: +forward `demand = runSpeed(0x34c)·throttle·fwdScale(0x5c0)`; reverse +`demand = −runSpeed·throttle` — **NO forwardThrottleScale in reverse** and no separate reverse +scale (full-lever reverse demands the full run top speed; the back cycle's clip-derived clamps +bound the actual backing pace). Port: PadRIO EmitButton(0x3F) → `gBTReverseHeld` → +`reverseThrust` (glass rigs; keyboard-bridge rigs also honor `key_throttle<0`). ⚠ The real +CAB's hardware red button is currently DEAD (streamed button mappings unconsumed — AddOrErase +still a Fail stub; the BTPadRIOActive accommodation excludes hardware RIO) — open-questions. +⚠ A held brake key can NEVER produce reverse: glass clamps the throttle channel to [0,1]; the +DEV keyboard-bridge zero detent latches a held sweep at exactly 0 (taps DO cross — the latch +needs prev>0). Player education: "hold ALT + keep the throttle open", exactly like the pod. + +**HARD-BRAKE slew + gyro lurch/judder (#102 root, ported 2026-08-14) [T1 decode / T2 bench]:** +the master perf (@0x4aa158-0x4aa365; part_013.c:3353-95) watches for a FORWARD leg cycle +meeting a NEGATIVE demand (the red-button throw at speed): engage-edge latches `+0x3f4` (the +recon's `airborneSelect` — **another jump-jet-family misread; it is the BRAKE flag**, and it +replicates via the type-8 record field so peers pick the rate too), `ForceUpdate(0x100)`, +swaps `forwardCycleRate(0x344)` to `+0x5bc` = the model's **SuperStopAcceleration** (the recon's +"airborneCycleRate"), and kicks the gyro with a random-sign Z torque+impulse (0.4). While +braking above `walkStrideLength`, the gyro takes a vertical 0.2 impulse every 0.4 s +(`gyroRumbleTimer`@0x5c4) — the pod's brake JUDDER. Release-edge restores `+0x5b8` ground +rate. −1.1f = authored-off sentinel; every shipped chassis is LIVE: heavies brake HARDER than +they accelerate (thor/vul/ava/snd 10→20), madcat 20→20, loki 15→15, but **owens 50→25 and +blkhawk 30→10 brake at half/a third of their ground slew** — the light sprinter's long coast +is authored. The pod communicated that coast with the cab shake; the un-ported port coasted +SILENTLY, which is the felt "hang" of #102. Port: mech4.cpp drive block, before the channel +advances; `[brake]` receipts under BT_GAIT_TRACE. + +**Gait-SM PARK facts (2026-08-14 bench matrix, night18/gaithang_bench.sh) [T1/T2]:** every +moving state's slew clamps are NONZERO clip-derived speeds (walk floor `standSpeed`, run floor +`reverseSpeedMax`, back-cycle ceiling `gimpSpeedMax` = sbr exit, −5.83 owens), so clips always +reach their finished-callbacks — the machine has no mid-cycle stall by construction, and a +144-clip sweep found NO mid-clip zero/negative root beats anywhere. Standing is the ONLY +rest, it never reposes the skeleton (authentic — the pose stays where the last clip left it; +wind-downs end in the authored stand pose so normal stops look clean), and the trn arm is the +one input-driven rebinder (SetLegAnimation resets the playhead — why "twisting unsticks it"). +A trn cut by the turn-stop exit parks MID-PIVOT (authentic; the next input re-drives it) — +**this is the #102 "leg in the air" statue**: bench D reproduced it deterministically (turn +pulse ends mid-trn → parked at legFrm=10, leg raised; any twist/throttle re-drives — Lynx's +exact rescue). The machine had the same state but NOBODY COULD SEE IT: the pod has no +external view of your own mech (the chase camera is a port/dev addition), and peers' mechs +are continuously re-driven by their own pilots. Owens reads worst because its mid-swing +amplitude is the largest of the 8 chassis (thigh −43° vs MadCat −27°). NOT-A-BUG verdict; +the felt "hang" half was the missing brake system above. +⚠ Recon split-cell corollary: the binary's SM switch reads the LIVE alarm cell after the +wind-down-gate/death-latch preamble; the port's split alarm/int pair must RE-SYNC before the +switch or the gate frame dispatches the stale state (fixed 2026-08-14, both channels). +Bench hooks: `BT_KEYSIM="rate:sec,..."` (scripted lever keys through the real +integrator+detent), `BT_KEYSIM_REV="t:dur"` (the 0x3F button), `BT_KEYSIM_TURN="t:dur"`. + ## Turn-in-place (trn, state 4) — AUTHENTIC dispatcher decoded (task #64, 2026-07-14) **The entry dispatcher is NOT in the Ghidra decomp** — it lives in the master-perf gap `0x4a9b5c–0x4ab188` (functions_index.tsv jumps FUN_004a9770→FUN_004ab188; the SOLE reader of diff --git a/context/open-questions.md b/context/open-questions.md index d869058..cf498b7 100644 --- a/context/open-questions.md +++ b/context/open-questions.md @@ -100,6 +100,14 @@ status vs the pod's 7-display / RGB-splitter / dual-sound-card rig: 3. Serial protocol timing/handshake vs a real RIO board (and the intercom path) — unverified. 4. `-platform pod` deliberately does NOT auto-enable `L4GAUGE` (each surface needs its own device); the pod bring-up procedure itself is undocumented → the Nick items above. + 5. **REVERSE is DEAD on the hardware-RIO cab (#102 audit side-finding, 2026-08-14) [T3 + code-read].** The real red button (0x3F) reaches `buttonGroup` but nothing consumes it: + the streamed record [2] route (`Button Throttle1 → attr 6 ReverseThrust@0x124`) dead-ends + on the unreconstructed `MechControlsMapper::AddOrErase` Fail stubs, and the + `BTPadRIOActive()`-gated `gBTReverseHeld` accommodation deliberately excludes hardware + RIO. Fix lane when cab work resumes: either reconstruct AddOrErase (the streamed button + mappings then drive attr 6 themselves — the authentic path) or widen the accommodation's + gate. Decide the three-rig matrix (DEV bridge / glass PadRIO / hardware RIO) explicitly. ## BINARY-COVERAGE AUDIT discoveries (2026-07-13, 6-agent decomp census) [T1 verified-uncited] New unaccounted functionality no prior list knew (addresses verified absent from game/+context/+docs): diff --git a/context/reconstruction-gotchas.md b/context/reconstruction-gotchas.md index b3d9793..d86778e 100644 --- a/context/reconstruction-gotchas.md +++ b/context/reconstruction-gotchas.md @@ -1128,3 +1128,26 @@ it can starve (LAMP.cpp's read survives because lamp flicker IS the intended output). (3) The live-human receipt loop cracked what two headless rigs could not: the injection path was clean, so the defect HAD to be presentation -- receipts proving delivery while the screen disagrees convict the renderer. + +## 35. THE SPLIT ALARM/INT CELL DISPATCHES STALE ON PREAMBLE TRANSITIONS (#102, 2026-08-14) + +In the binary, a gait SM's "state variable" and its AlarmIndicator LEVEL are +ONE cell (`+0x3b0` == `legStateAlarm.level`, `+0x728` == body's) -- the switch +reads it LIVE, so a preamble transition (the wind-down gate cutting 6-9 -> +Standing, a death latch binding 0x1c-0x1f) dispatches its NEW state the same +frame: with a reverse demand held, the gate frame falls straight into case 0 +-> SetLegAnimation(0x10), which REBINDS AND REWINDS the clip -- a parked pose +structurally cannot linger. The recon split the cell into an alarm + a +mirror int synced once at function top; every mid-preamble SetLevel left the +switch dispatching the STALE pre-transition case for one frame -- and any +read of the mirror between preamble steps (the gate's own state test after a +same-frame death latch) judged a dead value. +**Rules:** (1) when a recon splits a binary cell into alarm + mirror, RE-SYNC +the mirror after EVERY preamble step that can write the alarm, not just at +entry -- or read the alarm directly at each decision. (2) The binary's +same-frame fallthrough semantics (gate -> case 0 -> rebind -> advance) are +part of the state machine's correctness, not an optimization: the one-frame +stale dispatch is exactly one frame of "no exit condition tested" -- the +#102 class. (3) Sibling of gotcha 30 (one cell, many port stores) and the +namedClip aliasing class -- grep for `= (int)` alarm syncs when auditing any +split-cell machine. diff --git a/game/reconstructed/mech2.cpp b/game/reconstructed/mech2.cpp index d5d8bce..2edb44f 100644 --- a/game/reconstructed/mech2.cpp +++ b/game/reconstructed/mech2.cpp @@ -923,7 +923,9 @@ Scalar // run/run-to-walk transition, drop the gait alarm to "standing". // { - int state = legAnimationState; // this+0x3b0 + // live-cell read (binary: one field @0x3b0; a same-frame death latch + // above must not leave a stale 6-9 here for the gate to stomp) + int state = (int)legStateAlarm.GetLevel(); if (legCycleSpeed <= ZeroSpeed // this+0x348 && (state == 6 || state == 7 || state == 8 || state == 9)) { @@ -932,6 +934,16 @@ Scalar } } + // SAME-FRAME RE-DISPATCH (#102, 2026-08-14): the binary's switch re-reads + // the state cell AFTER the gate/death-latch preamble (part_012.c:17523 + // 'switch(*(param_1 + 0x3b0))' -- +0x3b0 IS the alarm level, one cell), so + // the frame the wind-down gate cuts to Standing dispatches case 0 at once + // and, with a reverse demand held, rebinds the reverse-entry clip the SAME + // frame (SetLegAnimation resets the playhead -- the pose can never linger). + // The recon's split alarm/int pair made the switch read the STALE pre-gate + // state for one frame; re-sync here restores the binary's dispatch. + legAnimationState = (int)legStateAlarm.GetLevel(); + switch (legAnimationState) // this+0x3b0 { case StandingAnimation: // 0 @@ -1268,6 +1280,12 @@ Scalar } } + // SAME-FRAME RE-DISPATCH (#102 parity twin): the binary's switch reads the + // live cell +0x728 after the death-latch preamble (FUN_004a5678 has no + // wind-down gate [T1 part_013.c:1-33]); re-sync so a just-latched crash + // clip dispatches this frame, not next. + bodyAnimationState = (int)bodyStateAlarm.GetLevel(); + switch (bodyAnimationState) // this+0x728 { case StandingAnimation: // 0 diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index ea2c3cf..b059174 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -3279,6 +3279,15 @@ void { if (dt > 0.0001f && dt < 0.5f) { + // BRAKE-RATE SELECT (#102, 2026-08-14): the binary's replicant ran + // IntegrateMotion (@004ab1c8) per frame, whose first line picks the + // slew from the replicated brake flag (mech4.cpp:298 -- that TU path + // is DEAD in the port, Mech::Simulate bypassed). The flag itself + // already replicates (type-8 record -> airborneSelect, mech.cpp + // ReadUpdateRecord); without this line a peer watched the master + // brake at superStopAcceleration while its own slew stayed at the + // ground rate. + forwardCycleRate = airborneSelect ? airborneCycleRate : groundCycleRate; // AUTHENTIC PEER HEADING (decomp FUN_004ab188/FUN_00409f58 via FUN_004ab1c8): // the original replicant integrates its heading INCREMENTALLY from the // CURRENT pose -- compose an exact rotation of (replicated yaw rate * dt) @@ -3925,6 +3934,73 @@ void // gBTInput. Everything below the reads (the lever/stick/ // twist integrators, detents, edge latches) is UNCHANGED. BTInputPoll(dt); + // BT_KEYSIM (issue #102 bench, 2026-08-14): scripted key-hold + // schedule -- overrides the polled lever/turn channels so a + // headless bench can drive the REAL virtual-controls chain + // (lever integrator + zero detent + gait SM), which the + // forcedThrottle harnesses bypass. Spec: comma-separated + // "rate:seconds" segments consumed in order; rate is written + // to gBTInput.leverRate verbatim (the key-hold rate is ~0.7; + // sign = key direction; 0 = keys at rest). After the last + // segment the lever stays at rest (a bench never mixes real + // keys in). BT_KEYSIM_TURN="start:dur" adds a full-right + // turn pulse in [start, start+dur) on the same clock (the + // twist-rescue leg of the #102 repro). + { + static const char *s_ksSpec = getenv("BT_KEYSIM"); + if (s_ksSpec && *s_ksSpec) + { + static float s_ksClock = 0.0f; + s_ksClock += dt; + float segEnd = 0.0f; int applied = 0; + for (const char *p = s_ksSpec; p && *p; ) + { + const float rate = (float)atof(p); + const char *colon = strchr(p, ':'); + if (!colon) break; + segEnd += (float)atof(colon + 1); + if (s_ksClock < segEnd) + { + gBTInput.leverRate = rate; + applied = 1; + break; + } + const char *comma = strchr(p, ','); + p = comma ? comma + 1 : 0; + } + if (!applied) + gBTInput.leverRate = 0.0f; // schedule exhausted + static const char *s_ktSpec = getenv("BT_KEYSIM_TURN"); + if (s_ktSpec && *s_ktSpec) + { + const float t0 = (float)atof(s_ktSpec); + const char *c2 = strchr(s_ktSpec, ':'); + const float tdur = c2 ? (float)atof(c2 + 1) : 0.0f; + if (s_ksClock >= t0 && s_ksClock < t0 + tdur) + { + gBTInput.turnActive = 1; + gBTInput.turnTarget = 1.0f; + } + } + // BT_KEYSIM_REV="start:dur": hold the pod's REVERSE + // THRUST button (unit 0x3F, LALT) in [start,start+dur) + // on the same clock -- drives gBTReverseHeld, the one + // chokepoint every rig funnels through (L4PADRIO + // EmitButton -> mechmppr reverseThrust). This is the + // AUTHENTIC reverse shape: throttle stays put, demand + // sign-flips (issue #102 repro). + static const char *s_krSpec = getenv("BT_KEYSIM_REV"); + if (s_krSpec && *s_krSpec) + { + extern int gBTReverseHeld; + const float r0 = (float)atof(s_krSpec); + const char *c3 = strchr(s_krSpec, ':'); + const float rdur = c3 ? (float)atof(c3 + 1) : 0.0f; + gBTReverseHeld = + (s_ksClock >= r0 && s_ksClock < r0 + rdur) ? 1 : 0; + } + } + } gBTDrive.keyFwd = gBTInput.leverRate > 0.0001f ? 1 : 0; gBTDrive.keyBack = gBTInput.leverRate < -0.0001f ? 1 : 0; gBTDrive.keyLeft = (gBTInput.turnActive && gBTInput.turnTarget < 0.0f) ? 1 : 0; @@ -5413,6 +5489,74 @@ void << " reverseSpeedMax=" << reverseSpeedMax << " target=" << bodyTargetSpeed << " split=" << s_realControls << "\n" << std::flush; } + // HARD-BRAKE SLEW + GYRO LURCH/JUDDER (issue #102, 2026-08-14) -- + // FUN_004a9b5c @0x4aa158-0x4aa365 (part_013.c:3353-3395 in the + // 2026-08-06 re-export; disasm scratchpad/night6/gap_4a9770.txt), + // transcribed field for field. When a FORWARD leg cycle meets a + // NEGATIVE demand (the red-button reverse throw at speed), the + // binary latches airborneSelect(+0x3f4) -- ANOTHER jump-jet-family + // misread: it is the BRAKE-ENGAGED flag, and +0x5bc + // ("airborneCycleRate") is the model's SuperStopAcceleration, the + // hard-brake slew -- swaps forwardCycleRate(+0x344) to it, ships + // the flag (ForceUpdate(0x100); the type-8 record field carries it + // so peers pick the brake rate too), and kicks the gyro with a + // random-sign Z lurch. While braking above the walk cap the gyro + // takes a vertical 0.2 impulse every 0.4 s (gyroRumbleTimer@0x5c4, + // zeroed by the clip loader) -- the pod's brake JUDDER, the cab + // shake that told the pilot "braking!" through the long coast. + // -1.1f = authored-off sentinel (no shipped chassis uses it; + // content: Owens brakes at HALF its ground rate 50->25, Blackhawk + // 30->10, the heavies 10->20). Without this block the port + // silently coasted at the ground slew with zero feedback -- the + // felt "hang" of #102. + if (airborneCycleRate != -1.1f) + { + MechControlsMapper *bmppr = MappingMapper(); + const Scalar bdmd = (bmppr != 0) ? bmppr->speedDemand : 0.0f; + if (legCycleSpeed > 0.0f && bdmd < 0.0f) + { + if (airborneSelect == 0) + { + airborneSelect = 1; // brake ENGAGE edge + ForceUpdate(0x100); + forwardCycleRate = airborneCycleRate; // 0x344 <- 0x5bc + if (gyroSubsystem != 0) + { + extern void GyroApplyDamageImpulse(Subsystem *, Scalar, Scalar, Scalar, Scalar); + extern void GyroApplyDamageTorque (Subsystem *, Scalar, Scalar, Scalar, Scalar); + Scalar r = RandomUnit(); + if (RandomUnit() > 0.5f) // _DAT_004ab170 + r = -r; + GyroApplyDamageTorque (gyroSubsystem, 0.0f, 0.0f, r, 0.4f); + GyroApplyDamageImpulse(gyroSubsystem, 0.0f, 0.0f, r, 0.4f); + } + if (getenv("BT_GAIT_TRACE")) + DEBUG_STREAM << "[brake] ENGAGE cyc=" << legCycleSpeed + << " dmd=" << bdmd << " rate=" << airborneCycleRate + << " (ground " << groundCycleRate << ")\n" << std::flush; + } + } + else if (airborneSelect != 0) + { + airborneSelect = 0; // brake RELEASE edge + ForceUpdate(0x100); + forwardCycleRate = groundCycleRate; // 0x344 <- 0x5b8 + if (getenv("BT_GAIT_TRACE")) + DEBUG_STREAM << "[brake] release\n" << std::flush; + } + } + if (airborneSelect != 0 && walkStrideLength < legCycleSpeed + && gyroSubsystem != 0) + { + if (gyroRumbleTimer > 0.0f) + gyroRumbleTimer -= dt; // +0x5c4 countdown + else + { + extern void GyroApplyDamageImpulse(Subsystem *, Scalar, Scalar, Scalar, Scalar); + GyroApplyDamageImpulse(gyroSubsystem, 0.0f, 1.0f, 0.0f, 0.2f); + gyroRumbleTimer = 0.4f; // the 0.4s judder period + } + } if (s_realControls) { // CHANNEL ROLES (task #49, disasm-corrected [T1]): in the binary diff --git a/scratchpad/night17/DAY_STATE.md b/scratchpad/night17/DAY_STATE.md index be3c903..13e3ac5 100644 --- a/scratchpad/night17/DAY_STATE.md +++ b/scratchpad/night17/DAY_STATE.md @@ -32,3 +32,71 @@ received); Elengil's pre-rotation steam_20260812.log; era answers (valve-boost l 450/800 pip, PPC-hit visuals for Cyd's scramble); Cyd PPC-scramble merge = post-Friday (rebase over palette work + dirty-skip token fix + 2-node bench). NEXT WEEK: BTSimClock migration per the census checklist (gyro item may land today instead). + +LATE-NIGHT TRACKER SWEEP (post-midnight): #151 resolved-by-#162 (eject -499 = self-blast -499 ++ death -500 + DUPLICATE death -500; now expects ~0 -- Oracle re-test Friday); #112 CLOSED +(fixed by #171, sweep receipts burst=1 universal); #147 NaN-trap receipt promoted ALWAYS-ON +(65b30d4) so Friday can name the NaN source; #153 CLOSED-AUTHENTIC (binary clamps elevation +only on input [T1 @004b5cf0]; snap-on-next-input = the machine; Recenter is twist-only). +HANDOUT REGEN TOMORROW must add the known-authentic-quirks lines: veteran heat is real in +4.10; Basic-mode elevation snaps on next pitch input (authentic); eject now costs ~all your +points (self-blast + death cost, the manual's own math); plus reword the old 'settles the +HUD horizon' phrasing (Oracle's question). + +FRIDAY DAYTIME (car session): full comment-thread sweep DONE (new memory: +read-ticket-threads-not-bodies). #151 CORRECTED (-499 IS authentic: suicide + death cost, +bench-proven on-ticket 08-10; my ~zero claim retracted, handout fixed, design call restored). +#104 rename HELD (the 360dps receipts say the NARC label may be truthful). #113 closed-faithful ++ the authored TURN RATES wired same day (cec6458: model+0x40 deg/s caps the steering; A/B +benched 43/69 CAP receipts vs zero; mad2 'LRM15' = nrk profile). #155 bank-capture half +ANSWERED: the machine never captured any bank (121 streamed rows zero eject-gated [T1]; +MechRIOMapper 0x200000 = PANIC+lamp only [T1]; engine dispatch = AND [T0]) -> the dead +eng/weapon MFDs are OUR bug; repro rig designed (BT_BTNTEST + [group-upd] walked/matched +while armed). SUNDAY SLATE: #155 mechanism hunt + fix; #102 forward/reverse detent; #125 +zone-edge; #27 clean retest note; #130 retest-likely-fixed. + +#155 CLOSED-OUT FRIDAY AFTERNOON (caa50ef + gotcha 34, 7b641f9): the dead banks were the +gauge renderer's change-XOR reading the mode MANAGER's shared previousModeMask scratch (the +authentic panic chatter stomps it per frame, eating SetPresetMode's page bits); one-line fix +(sample the renderer's OWN member); diagnosed via the operator's live mouse session (receipts +proved delivery while the screen held = presentation convicted), fix live-verified same +session (8 transitions / 4 exits / 2833 flap edges). Flicker stays authentic. SUNDAY SLATE +REMAINING: #102 forward/reverse detent, #125 first-destroyed-zone edge; plus tonight's field +returns. Rides the Sunday build with the turn rates. + +RADAR AUDIT (Friday evening, 3-agent, 800k tokens): #49 CLOSED operator-verified (c2193e2) +-- the static world feed restored (non-dynamic Terrain-graph pass in RebuildEntityGrid); +walls/buttes/hills/ridges/trees/buildings draw as authored pips on every map, zero new art. +Ledger: docs/RADAR_MAP_AUDIT.md. Authentic absences documented (wall10k boundary invisible +by authorship; unpipped props; no range rings; 45deg wedge). SUNDAY NOTES must carry: the +radar restoration headline + the two not-bugs (boundary, declutter) + the arena-edge era +question. Sunday build now carries: turn rates + #155 banks + #49 radar world. + +NIGHT18 (Friday evening, post-compaction): #102 OWENS RUN<->REVERSE. The #102 audit +(3-agent: binary/input/content + bench matrix night18/gaithang_bench.sh) found the port +was missing the machine's whole HARD-BRAKE system: master perf @0x4aa158-0x4aa365 swaps +the gait slew to the model's SuperStopAcceleration when a forward cycle meets a reverse +demand (+0x3f4 "airborneSelect" = the BRAKE latch, another jump-jet-family misread; ++0x5bc "airborneCycleRate" = the brake rate) + gyro random-sign lurch on engage + 0.4s +vertical judder above walk speed (gyroRumbleTimer@0x5c4). Content: heavies brake harder +than they accelerate (10->20), OWENS brakes at HALF (50->25) -- the sprinter's long +coast is authored; the pod communicated it through the cab shake, the port coasted +SILENTLY = the felt hang. PORTED (mech4 drive block, [brake] receipts) + the +same-frame re-dispatch parity fix (gotcha 35: split alarm/int cell dispatched stale on +gate/death-latch frames; both channels re-synced). Bench: ALT sign-flip at full run = +clean chain into reverse w/ brake receipts; held-brake-key = clean authored stand, zero +brake (authentic), twist arms trn from the park (the rescue). REVERSE INPUT TRUTH: red +button 0x3F/LALT sign-flip, demand = -runSpeed*throttle (NO fwdScale); brake keys can +NEVER reverse (throttle [0,1] like the pod lever) -> HANDOUT education line. Side-find: +hardware-RIO cab reverse is DEAD (AddOrErase stubs; open-questions row). KEYSIM bench +hooks added (BT_KEYSIM/_REV/_TURN). 674 worktree forensic pending -> ticket close. +SUNDAY build now carries: turn rates + #155 banks + #49 radar + #102 brake system. +NEXT: #125 first-destroyed-zone edge. +NIGHT18 addendum: 674 forensic RESOLVED without a repro run -- the 674 build boots the +GLASS profile by default (log: '[boot] platform profile: GLASS'), so PadRIO owned +reverseThrust and the BT_FORCE_FLIP negative-throttle path was stomped (rev=0 all run); +i.e. reverse at 674 was exclusively LALT on every rig. The statue itself = the trn +turn-stop MID-PIVOT park (authentic, pod-invisible: no external self-view existed); +bench D reproduced it at trn legFrm=10 + twist rescue. Peer brake-rate select restored +in the replicant motion path (IntegrateMotion:298 is dead code -- Simulate bypassed). +Final build: 20 benign LNK2019s exact. diff --git a/scratchpad/night18/gaithang674.sh b/scratchpad/night18/gaithang674.sh new file mode 100644 index 0000000..49f77e4 --- /dev/null +++ b/scratchpad/night18/gaithang674.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# ========================================================================= +# ISSUE #102 FORENSICS -- the 4.11.674 build (commit 137c151, the build +# Lynx reported against). Worktree C:/git/bt411-674. No BT_KEYSIM on +# 674, so the ALT demand shape rides the forced harness instead: +# BT_AUTODRIVE=1.0 + BT_FORCE_FLIP=14 (key_throttle sign-flips at t=14 -> +# reverseThrust=1 via the key_throttle<0 term). BT_PLATFORM deliberately +# UNSET: under glass the PadRIO-active accommodation (mechmppr ~1036) +# stomps reverseThrust back to gBTReverseHeld=0 and the flip dies. +# usage: gaithang674.sh [extra env pairs...] +# ========================================================================= +set -x +EXE=/c/git/bt411-674/build/Release/btl4.exe +cd /c/git/bt411-674/content || exit 1 + +TAG=$1; shift +sed 's/^experience=.*/experience=expert/' MP.EGG > GH674.EGG +sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=owens/" GH674.EGG +LOG=gh674_${TAG}.log +rm -f "$LOG" + +( export BT_START_INSIDE=1 BT_DEV_GAUGES=1 BT_LOG="$LOG" BT_AFFINITY=0x03 + export BT_GAIT_TRACE=1 BT_AUTODRIVE=1.0 BT_FORCE_FLIP=14 + for kv in "$@"; do export "$kv"; done + "$EXE" -egg GH674.EGG & + echo $! > /tmp/gh674.pid + cat /proc/$!/winpid > /tmp/gh674.winpid 2>/dev/null ) +sleep 55 +[ -f /tmp/gh674.winpid ] && taskkill //F //PID "$(cat /tmp/gh674.winpid)" > /dev/null 2>&1 +rm -f /tmp/gh674.pid /tmp/gh674.winpid +sleep 2 +echo "--- $LOG" +grep -ac "gaitSM" "$LOG" || true diff --git a/scratchpad/night18/gaithang_bench.sh b/scratchpad/night18/gaithang_bench.sh new file mode 100644 index 0000000..5627e18 --- /dev/null +++ b/scratchpad/night18/gaithang_bench.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# ========================================================================= +# ISSUE #102 -- OWENS RUN->REVERSE GAIT HANG (night18) +# Solo expert Owens, grass/day. BT_KEYSIM drives the REAL virtual-controls +# chain (lever integrator + ZERO DETENT + gait SM) on a schedule -- the +# forcedThrottle harnesses bypass the lever, which is where the suspect +# lives (mech4.cpp zero detent: a held sweep that crosses 0 latches at 0 +# until BOTH keys rest -> demand pinned to exactly 0.0 while reverse held). +# +# run A (repro): 3s rest, 10s full fwd (run), 20s HOLD BACK -- the +# Lynx shape. Twist pulse at t=38 (the rescue leg). +# run B (control): same but RELEASE 1.5s then re-press back -- the +# documented detent recovery; reverse must engage. +# +# Receipts: [gaitSM] per frame (legState/legCycle/legFrm/spd), [vctl] 1Hz +# (keys + lever). Park signature: legState=0 with legFrm frozen mid-clip, +# spd=0 while back key held; reverse states (16-19) never entered. +# usage: gaithang_bench.sh [extra env pairs...] +# ========================================================================= +set -x +. /c/git/bt411/scratchpad/night6/bench_common.sh +cd /c/git/bt411/content || exit 1 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +sleep 2 + +VARIANT=$1; shift +bt_expert_egg MP.EGG GH102.EGG +sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=owens/" GH102.EGG +LOG=gaithang_${VARIANT}.log +rm -f "$LOG" + +if [ "$VARIANT" = "A" ]; then + # S-key sweep shape (keyboard-bridge rigs only; dead channel on glass) + KS="0:3,0.7:10,-0.7:20,0:8" + KT="38:2.5" + KR="" + XTRA="" + DUR=55 +elif [ "$VARIANT" = "C" ]; then + # THE AUTHENTIC LALT SHAPE (glass rig = what Lynx flies): full forced + # throttle, REVERSE BUTTON held t=14..34 (gBTReverseHeld -> reverseThrust + # sign-flip), release at 34 = the recovery probe (a Standing-class park + # recovers on the demand flip; a frozen-clip park stays parked). + KS="0:1" + KT="" + KR="14:20" + XTRA="BT_AUTODRIVE=1.0" + DUR=55 +elif [ "$VARIANT" = "D" ]; then + # THE GLASS S-KEY SHAPE: demand pinned at EXACTLY 0 after a full run + # (PadRIO throttle clamps [0,1] -- S can never reverse; the keyboard- + # bridge detent pins the same way). BT_KEY_BRIDGE=1 forces the bridge + # so BT_KEYSIM's lever drives the mapper. Twist pulse at t=38 = the + # Lynx rescue. Park signature: legState=0, legFrm frozen != 0, spd=0. + KS="0:3,0.7:10,-0.7:20,0:10" + KT="38:2.5" + KR="" + XTRA="BT_KEY_BRIDGE=1" + DUR=55 +else + KS="0:3,0.7:10,-0.7:2,0:1.5,-0.7:15" + KT="" + KR="" + XTRA="" + DUR=45 +fi + +( export BT_GAIT_TRACE=1 BT_KEY_LOG=1 BT_KEYSIM="$KS" + [ -n "$KT" ] && export BT_KEYSIM_TURN="$KT" + [ -n "$KR" ] && export BT_KEYSIM_REV="$KR" + [ -n "$XTRA" ] && export $XTRA + for kv in "$@"; do export "$kv"; done + bt_launch "$LOG" GH102.EGG 0x03 ) +sleep $DUR +bt_kill_ours +sleep 3 +taskkill //F //IM btl4.exe > /dev/null 2>&1 +echo "--- $LOG" +grep -ac "gaitSM" "$LOG" +grep -a "vctl" "$LOG" | head -40