autopilotForce gains an optional PilotDebug out-param (mode/wishspeed/ vSafe/deficit/grounded) for debug harnesses; phys-deep gains LAW=assist A/B. 90-seed fuzz: 0 falls, 2 wedges — both PRE-EXISTING generation band bugs (wedge identically under the assist law): slant under-crossing wall face at channel level, island slope terrace leak. Forensics + the tri-scan invisible-wall method recorded in progress.md; fix deferred to a generation round (reshuffles every stream).
- commit
- 21441f9b17c0f95d42f5788cc5bb66a143ba1a15
- parent
- 16ac61af4b456a124b6d7ef1e642200dd5184a3b
- author
- Dami <dami.etoile@gmail.com>
| M | progress.md | 14 | ++++++++++++++ |
| M | src/ | 27 | +++++++++++++++++++++++++++ |
@@ -1147,6 +1147,20 @@ multiplier on the traction budget (same knob, now principled). Gates: 7
11471147 survivability seeds, all named scenarios, deep fuzz, determinism hash,11481148 re-pin scenario table.11491149 1150+**KNOWN GENERATION BUGS (M14a fuzz finds, pre-existing — wedge under BOTH1151+laws, rare 2/90 seeds, netted by respawn escalation; fix = a generation1152+round, it reshuffles every stream):** (a) apfuzz-81 s=41.9: seg2's1153+slant-long-d chute under-crosses seg0's channel with Δ0.55tr — its ribbon1154+wall tops (floor+0.55tr) form a face at exactly seg0's floor level, fully1155+blocking the channel (band overlap in cell (19,0): steep-part cells claim1156+bands that under-represent wall geometry). (b) apfuzz-58 s=330.3: an1157+island-run slope window climbs into island mass boxes (terrace band leak1158+on the slope part). Both diagnosed by scratch tri-scan-all.ts (point→1159+triangle distance over every co-live proxy — the "invisible wall" finder;1160+recreate from this note when needed). Marble telemetry: a one-frame1161+velocity REVERSAL at ratio ≈ restitution means a static face head-on;1162+constant-force zero-velocity equilibrium means normal through the center.1163+11501164 **M14b — Jumping as a decision.** Shim ph_marble_jump (top-up: velocity11511165 along normal SET to jumpImpulse, never added — deterministic height);11521166 autopilot commits when a gap/rise in the lookahead needs it AND the@@ -82,6 +82,16 @@ const AIR_HEIGHT = 0.45;
8282 const clamp = (v: number, lo: number, hi: number): number =>8383 v < lo ? lo : v > hi ? hi : v;8484 85+/** Per-step introspection (debug harnesses pass one in). */86+export interface PilotDebug {87+ mode?: string;88+ wishspeed?: number;89+ vSafe?: number;90+ deficit?: number;91+ grounded?: boolean;92+ look?: readonly [number, number, number];93+}94+8595 /**8696 * The complete autopilot step at a station. Same contract as8797 * rail.ts stationForce (drivers swap one call), plus a pilot.@@ -94,6 +104,7 @@ export function autopilotForce(
94104 mass: number,95105 nextRail: Rail | null = null,96106 pilot: Pilot = DEFAULT_PILOT,107+ dbg?: PilotDebug,97108 ): [number, number, number] | null {98109 const t = rail.tans[idx];99110 if (!t) return null;@@ -102,6 +113,7 @@ export function autopilotForce(
102113 // zones cancel part of gravity. (M14b adds the jump decision + air103114 // lineup on top.)104115 if (mod?.flight) {116+ if (dbg) dbg.mode = "flight";105117 if (mod.gravScale !== undefined && mod.gravScale !== 1) {106118 return [0, (1 - mod.gravScale) * -GRAVITY_Y * mass, 0];107119 }@@ -134,6 +146,11 @@ export function autopilotForce(
134146 const look = tanAt(k);135147 const sk = sAt(k);136148 if (!look || sk === null) break;149+ // The sweep stops at a flight zone: its rail "curvature" is the priced150+ // ballistic profile diving through the gap, not floor geometry —151+ // reading it as a crest braked marbles below launch speed at jump lips152+ // (they crept off the lip and wedged in the catch pan).153+ if (modAt(k)?.flight) break;137154 const ds = sk - prevS;138155 if (ds > 1e-6) {139156 const hp = Math.hypot(prev[0], prev[2]);@@ -201,6 +218,13 @@ export function autopilotForce(
201218 202219 const grounded = pos[1] - rail.pts[idx][1] < AIR_HEIGHT;203220 const out: [number, number, number] = [0, 0, 0];221+ if (dbg) {222+ dbg.wishspeed = wishspeed;223+ dbg.vSafe = vSafe;224+ dbg.grounded = grounded;225+ dbg.look = look;226+ dbg.mode = grounded ? "coast" : "air";227+ }204228 205229 if (grounded) {206230 // Project wishdir onto the ground plane (normal ≈ tangent-plane up)@@ -230,6 +254,7 @@ export function autopilotForce(
230254 }231255 const vAlongT = vel[0] * t[0] + vel[1] * t[1] + vel[2] * t[2];232256 if (vAlongT > vSafe) {257+ if (dbg) dbg.mode = "brake";233258 // Decisive brake above the planned envelope — its own clamp, like234259 // MBHaxe braking vs rolling authority.235260 const a = Math.min(A_BRAKE_MAX, 3 + (vAlongT - vSafe) * 2);@@ -239,7 +264,9 @@ export function autopilotForce(
239264 } else {240265 const vAlongW = vel[0] * wx + vel[1] * wy + vel[2] * wz;241266 const deficit = wishspeed - vAlongW;267+ if (dbg) dbg.deficit = deficit;242268 if (deficit > 0) {269+ if (dbg) dbg.mode = "accel";243270 // Icy: grip scales BOTH responsiveness and the ceiling — on ice244271 // the pilot wants the same speed and simply cannot have it.245272 const grip = mod?.icy ? 0.3 : 1;