FAILURE MAP
← Case archive

FA-87186 / Physics integrator stability / Open access

Baumgarte bias multiplies by the timestep · case 01

Penetration is corrected far too slowly and objects sink.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The bias is beta*dt*pen instead of beta/dt*pen.

VERIFIED REPAIR

Convert position error to velocity by dividing by dt.

Unsuccessful approach: Omitting dt entirely gives a frame-rate dependent correction.

Case contract

solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh): one normal contact, vn<0 approaching. bias=(beta/dt)*(depth-slop) if positive; bounce=-e*vn when vn<-e_thresh. Target separating speed is max(bias,bounce); impulse=(target-vn)/(ima+imb) clamped at 0 (no pulling). Zero summed inverse mass gives [0, vn]. Return [impulse, post velocity] rounded to 6.

Why this case matters

Game and robotics physics loops depend on integrator update order, step control and stabilization terms; a wrong decision point turns a stable simulation into drifting or exploding motion.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh):
    w = ima + imb
    if w == 0:
        return [0.0, round(vn, 6)]
    pen = depth - slop
    bias = beta * dt * pen if pen > 0 else 0.0
    bounce = -e * vn if vn < -e_thresh else 0.0
    target = max(bias, bounce)
    lam = (target - vn) / w
    if lam < 0:
        lam = 0.0
    return [round(lam, 6), round(vn + lam * w, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-3.643, 0.059, 1.411, 1.423, 0.3, 0.01, 0.016666666666666666, 0.0, 0.5], [1.596683, 0.882]], [[-4.07, 0.068, 1.833, 1.776, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [1.167636, 0.144]], [[-2.528, 0.038, 0.0, 0.785, 0.1, 0.01, 0.016666666666666666, 0.0, 1.0], [3.434395, 0.168]], [[-3.935, -0.001, 0.725, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [5.427586, 0.0]], [[1.105, 0.118, 0.831, 0.859, 0.3, 0.01, 0.03333333333333333, 0.3, 1.0], [0.0, 1.105]], [[-2.676, 0.035, 1.014, 1.893, 0.1, 0.02, 0.03333333333333333, 0.3, 0.5], [1.196698, 0.8028]], [[-3.01, 0.195, 0.0, 1.066, 0.2, 0.005, 0.016666666666666666, 0.0, 0.5], [4.962477, 2.28]], [[-4.873, 0.122, 1.161, 0.497, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [3.749698, 1.344]]], [[[-0.249, 0.164, 1.159, 1.499, 0.2, 0.005, 0.016666666666666666, 0.8, 1.0], [0.811512, 1.908]], [[-3.51, 0.046, 1.742, 0.0, 0.1, 0.01, 0.016666666666666666, 0.8, 1.0], [3.626866, 2.808]], [[0.898, 0.047, 1.479, 1.652, 0.1, 0.005, 0.03333333333333333, 0.0, 0.5], [0.0, 0.898]], [[-1.806, 0.01, 0.207, 1.574, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [1.318248, 0.5418]], [[-0.597, 0.075, 0.0, 1.813, 0.2, 0.01, 0.03333333333333333, 0.8, 0.5], [0.592719, 0.4776]], [[0.906, 0.171, 1.426, 0.0, 0.2, 0.01, 0.03333333333333333, 0.8, 1.0], [0.042076, 0.966]], [[0.298, 0.166, 0.721, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [2.016644, 1.752]], [[-1.029, 0.163, 0.695, 0.376, 0.3, 0.01, 0.016666666666666666, 0.3, 1.0], [3.532213, 2.754]]], [[[0.862, 0.12, 1.337, 0.0, 0.2, 0.01, 0.016666666666666666, 0.3, 1.0], [0.342558, 1.32]], [[-4.634, 0.185, 0.994, 1.909, 0.3, 0.01, 0.03333333333333333, 0.8, 1.0], [2.873303, 3.7072]], [[0.364, 0.162, 1.848, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [0.725108, 1.704]], [[-3.418, 0.042, 0.542, 1.941, 0.3, 0.005, 0.03333333333333333, 0.3, 0.5], [1.789529, 1.0254]], [[-3.134, 0.061, 0.847, 1.706, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [1.595848, 0.9402]], [[-0.503, -0.016, 0.0, 1.19, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [0.422689, 0.0]], [[-3.541, 0.082, 0.0, 1.89, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [2.330688, 0.864]], [[-3.326, 0.068, 0.0, 1.572, 0.2, 0.02, 0.03333333333333333, 0.0, 1.0], [2.298982, 0.288]]], [[[-1.237, 0.163, 0.957, 0.0, 0.2, 0.01, 0.016666666666666666, 0.8, 0.5], [3.211076, 1.836]], [[-3.743, 0.04, 0.0, 0.113, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [43.061062, 1.1229]], [[-4.633, 0.14, 0.0, 0.0, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, -4.633]], [[-4.417, 0.068, 0.448, 0.0, 0.3, 0.005, 0.03333333333333333, 0.0, 0.5], [11.125, 0.567]], [[-0.921, 0.033, 0.727, 0.0, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [1.37414, 0.078]], [[0.397, 0.11, 0.0, 0.983, 0.2, 0.005, 0.03333333333333333, 0.3, 1.0], [0.23703, 0.63]], [[1.385, 0.138, 0.0, 0.432, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.349537, 1.536]], [[0.68, 0.139, 0.0, 0.0, 0.2, 0.005, 0.03333333333333333, 0.8, 1.0], [0.0, 0.68]]], [[[-0.356, 0.162, 0.573, 0.0, 0.1, 0.005, 0.016666666666666666, 0.0, 0.5], [2.265271, 0.942]], [[-0.664, 0.157, 0.422, 1.429, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [0.580767, 0.411]], [[1.731, 0.16, 0.639, 1.101, 0.1, 0.005, 0.016666666666666666, 0.8, 0.5], [0.0, 1.731]], [[0.523, 0.153, 0.986, 1.008, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [0.168004, 0.858]], [[-2.132, -0.019, 0.68, 0.901, 0.3, 0.005, 0.016666666666666666, 0.3, 1.0], [1.753068, 0.6396]], [[-2.447, 0.193, 1.933, 1.186, 0.2, 0.02, 0.016666666666666666, 0.0, 1.0], [1.450144, 2.076]], [[1.424, 0.05, 0.809, 1.444, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, 1.424]], [[-0.863, 0.138, 0.0, 0.0, 0.1, 0.005, 0.016666666666666666, 0.3, 0.5], [0.0, -0.863]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[1.285549, 0.000245][1.596683, 0.882]Failed
case 1[1.127781, 0.00016][1.167636, 0.144]Failed
case 2[3.220442, 4.7e-05][3.434395, 0.168]Failed
case 3[5.427586, 0.0][5.427586, 0.0]Passed
case 4[0.0, 1.105][0.0, 1.105]Passed
case 5[1.196698, 0.8028][1.196698, 0.8028]Passed
case 6[2.824234, 0.000633][4.962477, 2.28]Failed
case 7[2.939308, 0.000373][3.749698, 1.344]Failed

SHA-256 / 40c8202e0632f22234d840a91540f7498116bdc35b3d927d7d1f324b2ad77ffe

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh):
    w = ima + imb
    if w == 0:
        return [0.0, round(vn, 6)]
    pen = depth - slop
    bias = beta * pen if pen > 0 else 0.0
    bounce = -e * vn if vn < -e_thresh else 0.0
    target = max(bias, bounce)
    lam = (target - vn) / w
    if lam < 0:
        lam = 0.0
    return [round(lam, 6), round(vn + lam * w, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-3.643, 0.059, 1.411, 1.423, 0.3, 0.01, 0.016666666666666666, 0.0, 0.5], [1.596683, 0.882]], [[-4.07, 0.068, 1.833, 1.776, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [1.167636, 0.144]], [[-2.528, 0.038, 0.0, 0.785, 0.1, 0.01, 0.016666666666666666, 0.0, 1.0], [3.434395, 0.168]], [[-3.935, -0.001, 0.725, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [5.427586, 0.0]], [[1.105, 0.118, 0.831, 0.859, 0.3, 0.01, 0.03333333333333333, 0.3, 1.0], [0.0, 1.105]], [[-2.676, 0.035, 1.014, 1.893, 0.1, 0.02, 0.03333333333333333, 0.3, 0.5], [1.196698, 0.8028]], [[-3.01, 0.195, 0.0, 1.066, 0.2, 0.005, 0.016666666666666666, 0.0, 0.5], [4.962477, 2.28]], [[-4.873, 0.122, 1.161, 0.497, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [3.749698, 1.344]]], [[[-0.249, 0.164, 1.159, 1.499, 0.2, 0.005, 0.016666666666666666, 0.8, 1.0], [0.811512, 1.908]], [[-3.51, 0.046, 1.742, 0.0, 0.1, 0.01, 0.016666666666666666, 0.8, 1.0], [3.626866, 2.808]], [[0.898, 0.047, 1.479, 1.652, 0.1, 0.005, 0.03333333333333333, 0.0, 0.5], [0.0, 0.898]], [[-1.806, 0.01, 0.207, 1.574, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [1.318248, 0.5418]], [[-0.597, 0.075, 0.0, 1.813, 0.2, 0.01, 0.03333333333333333, 0.8, 0.5], [0.592719, 0.4776]], [[0.906, 0.171, 1.426, 0.0, 0.2, 0.01, 0.03333333333333333, 0.8, 1.0], [0.042076, 0.966]], [[0.298, 0.166, 0.721, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [2.016644, 1.752]], [[-1.029, 0.163, 0.695, 0.376, 0.3, 0.01, 0.016666666666666666, 0.3, 1.0], [3.532213, 2.754]]], [[[0.862, 0.12, 1.337, 0.0, 0.2, 0.01, 0.016666666666666666, 0.3, 1.0], [0.342558, 1.32]], [[-4.634, 0.185, 0.994, 1.909, 0.3, 0.01, 0.03333333333333333, 0.8, 1.0], [2.873303, 3.7072]], [[0.364, 0.162, 1.848, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [0.725108, 1.704]], [[-3.418, 0.042, 0.542, 1.941, 0.3, 0.005, 0.03333333333333333, 0.3, 0.5], [1.789529, 1.0254]], [[-3.134, 0.061, 0.847, 1.706, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [1.595848, 0.9402]], [[-0.503, -0.016, 0.0, 1.19, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [0.422689, 0.0]], [[-3.541, 0.082, 0.0, 1.89, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [2.330688, 0.864]], [[-3.326, 0.068, 0.0, 1.572, 0.2, 0.02, 0.03333333333333333, 0.0, 1.0], [2.298982, 0.288]]], [[[-1.237, 0.163, 0.957, 0.0, 0.2, 0.01, 0.016666666666666666, 0.8, 0.5], [3.211076, 1.836]], [[-3.743, 0.04, 0.0, 0.113, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [43.061062, 1.1229]], [[-4.633, 0.14, 0.0, 0.0, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, -4.633]], [[-4.417, 0.068, 0.448, 0.0, 0.3, 0.005, 0.03333333333333333, 0.0, 0.5], [11.125, 0.567]], [[-0.921, 0.033, 0.727, 0.0, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [1.37414, 0.078]], [[0.397, 0.11, 0.0, 0.983, 0.2, 0.005, 0.03333333333333333, 0.3, 1.0], [0.23703, 0.63]], [[1.385, 0.138, 0.0, 0.432, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.349537, 1.536]], [[0.68, 0.139, 0.0, 0.0, 0.2, 0.005, 0.03333333333333333, 0.8, 1.0], [0.0, 0.68]]], [[[-0.356, 0.162, 0.573, 0.0, 0.1, 0.005, 0.016666666666666666, 0.0, 0.5], [2.265271, 0.942]], [[-0.664, 0.157, 0.422, 1.429, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [0.580767, 0.411]], [[1.731, 0.16, 0.639, 1.101, 0.1, 0.005, 0.016666666666666666, 0.8, 0.5], [0.0, 1.731]], [[0.523, 0.153, 0.986, 1.008, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [0.168004, 0.858]], [[-2.132, -0.019, 0.68, 0.901, 0.3, 0.005, 0.016666666666666666, 0.3, 1.0], [1.753068, 0.6396]], [[-2.447, 0.193, 1.933, 1.186, 0.2, 0.02, 0.016666666666666666, 0.0, 1.0], [1.450144, 2.076]], [[1.424, 0.05, 0.809, 1.444, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, 1.424]], [[-0.863, 0.138, 0.0, 0.0, 0.1, 0.005, 0.016666666666666666, 0.3, 0.5], [0.0, -0.863]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[1.290649, 0.0147][1.596683, 0.882]Failed
case 1[1.129066, 0.0048][1.167636, 0.144]Failed
case 2[3.223949, 0.0028][3.434395, 0.168]Failed
case 3[5.427586, 0.0][5.427586, 0.0]Passed
case 4[0.0, 1.105][0.0, 1.105]Passed
case 5[1.196698, 0.8028][1.196698, 0.8028]Passed
case 6[2.859287, 0.038][4.962477, 2.28]Failed
case 7[2.952593, 0.0224][3.749698, 1.344]Failed

SHA-256 / 195c1a0b3a7d5ce260a8c668351b269c6a498ad69ff7ab25fdc4dbbe513e8d93

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh):
    w = ima + imb
    if w == 0:
        return [0.0, round(vn, 6)]
    pen = depth - slop
    bias = beta / dt * pen if pen > 0 else 0.0
    bounce = -e * vn if vn < -e_thresh else 0.0
    target = max(bias, bounce)
    lam = (target - vn) / w
    if lam < 0:
        lam = 0.0
    return [round(lam, 6), round(vn + lam * w, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[-3.643, 0.059, 1.411, 1.423, 0.3, 0.01, 0.016666666666666666, 0.0, 0.5], [1.596683, 0.882]], [[-4.07, 0.068, 1.833, 1.776, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [1.167636, 0.144]], [[-2.528, 0.038, 0.0, 0.785, 0.1, 0.01, 0.016666666666666666, 0.0, 1.0], [3.434395, 0.168]], [[-3.935, -0.001, 0.725, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [5.427586, 0.0]], [[1.105, 0.118, 0.831, 0.859, 0.3, 0.01, 0.03333333333333333, 0.3, 1.0], [0.0, 1.105]], [[-2.676, 0.035, 1.014, 1.893, 0.1, 0.02, 0.03333333333333333, 0.3, 0.5], [1.196698, 0.8028]], [[-3.01, 0.195, 0.0, 1.066, 0.2, 0.005, 0.016666666666666666, 0.0, 0.5], [4.962477, 2.28]], [[-4.873, 0.122, 1.161, 0.497, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [3.749698, 1.344]]], [[[-0.249, 0.164, 1.159, 1.499, 0.2, 0.005, 0.016666666666666666, 0.8, 1.0], [0.811512, 1.908]], [[-3.51, 0.046, 1.742, 0.0, 0.1, 0.01, 0.016666666666666666, 0.8, 1.0], [3.626866, 2.808]], [[0.898, 0.047, 1.479, 1.652, 0.1, 0.005, 0.03333333333333333, 0.0, 0.5], [0.0, 0.898]], [[-1.806, 0.01, 0.207, 1.574, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [1.318248, 0.5418]], [[-0.597, 0.075, 0.0, 1.813, 0.2, 0.01, 0.03333333333333333, 0.8, 0.5], [0.592719, 0.4776]], [[0.906, 0.171, 1.426, 0.0, 0.2, 0.01, 0.03333333333333333, 0.8, 1.0], [0.042076, 0.966]], [[0.298, 0.166, 0.721, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [2.016644, 1.752]], [[-1.029, 0.163, 0.695, 0.376, 0.3, 0.01, 0.016666666666666666, 0.3, 1.0], [3.532213, 2.754]]], [[[0.862, 0.12, 1.337, 0.0, 0.2, 0.01, 0.016666666666666666, 0.3, 1.0], [0.342558, 1.32]], [[-4.634, 0.185, 0.994, 1.909, 0.3, 0.01, 0.03333333333333333, 0.8, 1.0], [2.873303, 3.7072]], [[0.364, 0.162, 1.848, 0.0, 0.2, 0.02, 0.016666666666666666, 0.0, 0.5], [0.725108, 1.704]], [[-3.418, 0.042, 0.542, 1.941, 0.3, 0.005, 0.03333333333333333, 0.3, 0.5], [1.789529, 1.0254]], [[-3.134, 0.061, 0.847, 1.706, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [1.595848, 0.9402]], [[-0.503, -0.016, 0.0, 1.19, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [0.422689, 0.0]], [[-3.541, 0.082, 0.0, 1.89, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [2.330688, 0.864]], [[-3.326, 0.068, 0.0, 1.572, 0.2, 0.02, 0.03333333333333333, 0.0, 1.0], [2.298982, 0.288]]], [[[-1.237, 0.163, 0.957, 0.0, 0.2, 0.01, 0.016666666666666666, 0.8, 0.5], [3.211076, 1.836]], [[-3.743, 0.04, 0.0, 0.113, 0.3, 0.02, 0.016666666666666666, 0.3, 0.5], [43.061062, 1.1229]], [[-4.633, 0.14, 0.0, 0.0, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, -4.633]], [[-4.417, 0.068, 0.448, 0.0, 0.3, 0.005, 0.03333333333333333, 0.0, 0.5], [11.125, 0.567]], [[-0.921, 0.033, 0.727, 0.0, 0.2, 0.02, 0.03333333333333333, 0.0, 0.5], [1.37414, 0.078]], [[0.397, 0.11, 0.0, 0.983, 0.2, 0.005, 0.03333333333333333, 0.3, 1.0], [0.23703, 0.63]], [[1.385, 0.138, 0.0, 0.432, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.349537, 1.536]], [[0.68, 0.139, 0.0, 0.0, 0.2, 0.005, 0.03333333333333333, 0.8, 1.0], [0.0, 0.68]]], [[[-0.356, 0.162, 0.573, 0.0, 0.1, 0.005, 0.016666666666666666, 0.0, 0.5], [2.265271, 0.942]], [[-0.664, 0.157, 0.422, 1.429, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [0.580767, 0.411]], [[1.731, 0.16, 0.639, 1.101, 0.1, 0.005, 0.016666666666666666, 0.8, 0.5], [0.0, 1.731]], [[0.523, 0.153, 0.986, 1.008, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [0.168004, 0.858]], [[-2.132, -0.019, 0.68, 0.901, 0.3, 0.005, 0.016666666666666666, 0.3, 1.0], [1.753068, 0.6396]], [[-2.447, 0.193, 1.933, 1.186, 0.2, 0.02, 0.016666666666666666, 0.0, 1.0], [1.450144, 2.076]], [[1.424, 0.05, 0.809, 1.444, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, 1.424]], [[-0.863, 0.138, 0.0, 0.0, 0.1, 0.005, 0.016666666666666666, 0.3, 0.5], [0.0, -0.863]]]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("case %d" % i, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
case 0[1.596683, 0.882][1.596683, 0.882]Passed
case 1[1.167636, 0.144][1.167636, 0.144]Passed
case 2[3.434395, 0.168][3.434395, 0.168]Passed
case 3[5.427586, 0.0][5.427586, 0.0]Passed
case 4[0.0, 1.105][0.0, 1.105]Passed
case 5[1.196698, 0.8028][1.196698, 0.8028]Passed
case 6[4.962477, 2.28][4.962477, 2.28]Passed
case 7[3.749698, 1.344][3.749698, 1.344]Passed

SHA-256 / b3cd13a4f77678221951607f81f16ae9866f2c5d8103cf23ae35017a0c1205a8

Verification & scope

A deterministic bounded teaching model with stipulated toy conventions and rounded float output; not a production physics engine or a proof of numerical stability. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:50:56.434910+00:00.

Case digest / 48794b1d55101e538639b7d1e5b23a6735b367058e174aa8ee7f45b26a14c4b8