{"abstract":"Light bodies get tiny impulses and heavy bodies are over-corrected.","category":"Physics integrator stability","checks":8,"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.","contract_signature":"vn, depth, ima, imb, beta, slop, dt, e, e_thresh","evaluation_group":"w2-physics_integrator_stability-baumgarte-contact-impulse","failed_approach":"Dividing by only the larger inverse mass ignores the other body.","family":"w2-physics_integrator_stability-baumgarte-contact-impulse-effective-mass","id":"FA-87206","implementations":{"attempt":{"sha256":"cd8731eda3df48aca54c647b98116be832ddb5872542708c23fb7d564821d7be","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh):\n    w = ima + imb\n    if w == 0:\n        return [0.0, round(vn, 6)]\n    pen = depth - slop\n    bias = beta / dt * pen if pen > 0 else 0.0\n    bounce = -e * vn if vn < -e_thresh else 0.0\n    target = max(bias, bounce)\n    lam = (target - vn) / max(ima, imb)\n    if lam < 0:\n        lam = 0.0\n    return [round(lam, 6), round(vn + lam * w, 6)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[-4.177, 0.112, 0.0, 0.0, 0.1, 0.005, 0.016666666666666666, 0.3, 1.0], [0.0, -4.177]], [[1.41, 0.135, 0.151, 1.614, 0.3, 0.01, 0.016666666666666666, 0.0, 0.5], [0.475921, 2.25]], [[-3.935, -0.001, 0.725, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [5.427586, 0.0]], [[-1.967, 0.032, 0.824, 0.115, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [2.723216, 0.5901]], [[0.508, 0.146, 0.0, 0.354, 0.2, 0.01, 0.03333333333333333, 0.8, 1.0], [0.870056, 0.816]], [[1.262, 0.19, 1.184, 1.117, 0.1, 0.005, 0.03333333333333333, 0.8, 1.0], [0.0, 1.262]], [[-0.308, 0.163, 0.198, 1.287, 0.3, 0.02, 0.03333333333333333, 0.8, 0.5], [1.074074, 1.287]], [[-1.72, 0.144, 0.0, 0.0, 0.2, 0.01, 0.016666666666666666, 0.3, 1.0], [0.0, -1.72]]], [[[0.591, 0.063, 0.548, 0.151, 0.1, 0.005, 0.016666666666666666, 0.0, 1.0], [0.0, 0.591]], [[-1.309, 0.06, 0.588, 0.3, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [2.653378, 1.0472]], [[-1.029, 0.163, 0.695, 0.376, 0.3, 0.01, 0.016666666666666666, 0.3, 1.0], [3.532213, 2.754]], [[0.387, 0.038, 1.153, 0.0, 0.1, 0.01, 0.016666666666666666, 0.8, 0.5], [0.0, 0.387]], [[0.579, 0.19, 1.545, 1.81, 0.2, 0.02, 0.03333333333333333, 0.8, 0.5], [0.131446, 1.02]], [[-0.08, 0.034, 0.0, 1.484, 0.3, 0.005, 0.03333333333333333, 0.0, 0.5], [0.229784, 0.261]], [[-2.861, 0.183, 0.0, 1.604, 0.2, 0.02, 0.03333333333333333, 0.0, 1.0], [2.393392, 0.978]], [[1.423, 0.017, 0.0, 0.597, 0.2, 0.005, 0.03333333333333333, 0.3, 1.0], [0.0, 1.423]]], [[[-3.757, 0.012, 1.496, 1.54, 0.3, 0.01, 0.03333333333333333, 0.3, 0.5], [1.608729, 1.1271]], [[-3.134, 0.061, 0.847, 1.706, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [1.595848, 0.9402]], [[-2.036, -0.001, 1.318, 0.182, 0.3, 0.01, 0.03333333333333333, 0.3, 0.5], [1.764533, 0.6108]], [[-0.903, 0.047, 0.0, 0.0, 0.1, 0.02, 0.03333333333333333, 0.0, 1.0], [0.0, -0.903]], [[-1.453, 0.06, 0.0, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.0, -1.453]], [[-1.057, 0.121, 1.527, 0.0, 0.1, 0.01, 0.03333333333333333, 0.8, 0.5], [1.245972, 0.8456]], [[-3.223, 0.016, 0.0, 0.775, 0.3, 0.02, 0.03333333333333333, 0.0, 0.5], [4.15871, 0.0]], [[0.409, 0.029, 0.104, 0.0, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [0.0, 0.409]]], [[[1.004, 0.112, 0.796, 0.0, 0.1, 0.01, 0.03333333333333333, 0.8, 1.0], [0.0, 1.004]], [[-4.647, 0.009, 0.0, 0.0, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [0.0, -4.647]], [[-4.992, 0.109, 1.939, 1.518, 0.1, 0.005, 0.03333333333333333, 0.0, 0.5], [1.534278, 0.312]], [[0.08, 0.097, 0.146, 0.0, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [10.794521, 1.656]], [[-1.618, 0.083, 0.255, 0.217, 0.3, 0.01, 0.03333333333333333, 0.8, 0.5], [6.170339, 1.2944]], [[-4.633, 0.14, 0.0, 0.0, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, -4.633]], [[-4.858, 0.174, 1.743, 0.441, 0.3, 0.005, 0.03333333333333333, 0.0, 1.0], [2.920788, 1.521]], [[-4.768, 0.04, 1.908, 1.371, 0.3, 0.01, 0.016666666666666666, 0.8, 1.0], [2.617383, 3.8144]]], [[[-2.096, 0.099, 1.34, 1.141, 0.3, 0.02, 0.03333333333333333, 0.3, 0.5], [1.131399, 0.711]], [[-2.365, 0.109, 1.976, 0.0, 0.3, 0.02, 0.03333333333333333, 0.8, 1.0], [2.154352, 1.892]], [[-2.015, 0.144, 1.236, 0.634, 0.2, 0.02, 0.03333333333333333, 0.8, 1.0], [1.939572, 1.612]], [[-0.664, 0.157, 0.422, 1.429, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [0.580767, 0.411]], [[-2.77, 0.145, 0.0, 0.0, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [0.0, -2.77]], [[-3.183, 0.12, 0.0, 0.0, 0.2, 0.005, 0.016666666666666666, 0.0, 0.5], [0.0, -3.183]], [[0.78, 0.12, 1.491, 1.397, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.186981, 1.32]], [[1.967, 0.183, 0.871, 0.109, 0.1, 0.01, 0.016666666666666666, 0.3, 0.5], [0.0, 1.967]]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"case %d\" % i, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"},"broken":{"sha256":"272d9ace52c6739b2acb3559730cb946c334bedd2955d842f61782f84fe1a9cb","source":"\"\"\"Failure Map reference implementation. Python standard library only.\"\"\"\nimport json\nimport math\nN = 1\nobservations = []\ndef solve(vn, depth, ima, imb, beta, slop, dt, e, e_thresh):\n    w = ima + imb\n    if w == 0:\n        return [0.0, round(vn, 6)]\n    pen = depth - slop\n    bias = beta / dt * pen if pen > 0 else 0.0\n    bounce = -e * vn if vn < -e_thresh else 0.0\n    target = max(bias, bounce)\n    lam = (target - vn) * w\n    if lam < 0:\n        lam = 0.0\n    return [round(lam, 6), round(vn + lam * w, 6)]\ndef check(label, actual, expected):\n    observations.append({\"check\": label, \"actual\": actual, \"expected\": expected, \"passed\": actual == expected})\nfixtures = [[[[-4.177, 0.112, 0.0, 0.0, 0.1, 0.005, 0.016666666666666666, 0.3, 1.0], [0.0, -4.177]], [[1.41, 0.135, 0.151, 1.614, 0.3, 0.01, 0.016666666666666666, 0.0, 0.5], [0.475921, 2.25]], [[-3.935, -0.001, 0.725, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 1.0], [5.427586, 0.0]], [[-1.967, 0.032, 0.824, 0.115, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [2.723216, 0.5901]], [[0.508, 0.146, 0.0, 0.354, 0.2, 0.01, 0.03333333333333333, 0.8, 1.0], [0.870056, 0.816]], [[1.262, 0.19, 1.184, 1.117, 0.1, 0.005, 0.03333333333333333, 0.8, 1.0], [0.0, 1.262]], [[-0.308, 0.163, 0.198, 1.287, 0.3, 0.02, 0.03333333333333333, 0.8, 0.5], [1.074074, 1.287]], [[-1.72, 0.144, 0.0, 0.0, 0.2, 0.01, 0.016666666666666666, 0.3, 1.0], [0.0, -1.72]]], [[[0.591, 0.063, 0.548, 0.151, 0.1, 0.005, 0.016666666666666666, 0.0, 1.0], [0.0, 0.591]], [[-1.309, 0.06, 0.588, 0.3, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [2.653378, 1.0472]], [[-1.029, 0.163, 0.695, 0.376, 0.3, 0.01, 0.016666666666666666, 0.3, 1.0], [3.532213, 2.754]], [[0.387, 0.038, 1.153, 0.0, 0.1, 0.01, 0.016666666666666666, 0.8, 0.5], [0.0, 0.387]], [[0.579, 0.19, 1.545, 1.81, 0.2, 0.02, 0.03333333333333333, 0.8, 0.5], [0.131446, 1.02]], [[-0.08, 0.034, 0.0, 1.484, 0.3, 0.005, 0.03333333333333333, 0.0, 0.5], [0.229784, 0.261]], [[-2.861, 0.183, 0.0, 1.604, 0.2, 0.02, 0.03333333333333333, 0.0, 1.0], [2.393392, 0.978]], [[1.423, 0.017, 0.0, 0.597, 0.2, 0.005, 0.03333333333333333, 0.3, 1.0], [0.0, 1.423]]], [[[-3.757, 0.012, 1.496, 1.54, 0.3, 0.01, 0.03333333333333333, 0.3, 0.5], [1.608729, 1.1271]], [[-3.134, 0.061, 0.847, 1.706, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [1.595848, 0.9402]], [[-2.036, -0.001, 1.318, 0.182, 0.3, 0.01, 0.03333333333333333, 0.3, 0.5], [1.764533, 0.6108]], [[-0.903, 0.047, 0.0, 0.0, 0.1, 0.02, 0.03333333333333333, 0.0, 1.0], [0.0, -0.903]], [[-1.453, 0.06, 0.0, 0.0, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.0, -1.453]], [[-1.057, 0.121, 1.527, 0.0, 0.1, 0.01, 0.03333333333333333, 0.8, 0.5], [1.245972, 0.8456]], [[-3.223, 0.016, 0.0, 0.775, 0.3, 0.02, 0.03333333333333333, 0.0, 0.5], [4.15871, 0.0]], [[0.409, 0.029, 0.104, 0.0, 0.1, 0.01, 0.016666666666666666, 0.3, 1.0], [0.0, 0.409]]], [[[1.004, 0.112, 0.796, 0.0, 0.1, 0.01, 0.03333333333333333, 0.8, 1.0], [0.0, 1.004]], [[-4.647, 0.009, 0.0, 0.0, 0.3, 0.005, 0.03333333333333333, 0.3, 1.0], [0.0, -4.647]], [[-4.992, 0.109, 1.939, 1.518, 0.1, 0.005, 0.03333333333333333, 0.0, 0.5], [1.534278, 0.312]], [[0.08, 0.097, 0.146, 0.0, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [10.794521, 1.656]], [[-1.618, 0.083, 0.255, 0.217, 0.3, 0.01, 0.03333333333333333, 0.8, 0.5], [6.170339, 1.2944]], [[-4.633, 0.14, 0.0, 0.0, 0.1, 0.02, 0.016666666666666666, 0.0, 1.0], [0.0, -4.633]], [[-4.858, 0.174, 1.743, 0.441, 0.3, 0.005, 0.03333333333333333, 0.0, 1.0], [2.920788, 1.521]], [[-4.768, 0.04, 1.908, 1.371, 0.3, 0.01, 0.016666666666666666, 0.8, 1.0], [2.617383, 3.8144]]], [[[-2.096, 0.099, 1.34, 1.141, 0.3, 0.02, 0.03333333333333333, 0.3, 0.5], [1.131399, 0.711]], [[-2.365, 0.109, 1.976, 0.0, 0.3, 0.02, 0.03333333333333333, 0.8, 1.0], [2.154352, 1.892]], [[-2.015, 0.144, 1.236, 0.634, 0.2, 0.02, 0.03333333333333333, 0.8, 1.0], [1.939572, 1.612]], [[-0.664, 0.157, 0.422, 1.429, 0.1, 0.02, 0.03333333333333333, 0.0, 0.5], [0.580767, 0.411]], [[-2.77, 0.145, 0.0, 0.0, 0.3, 0.005, 0.016666666666666666, 0.8, 0.5], [0.0, -2.77]], [[-3.183, 0.12, 0.0, 0.0, 0.2, 0.005, 0.016666666666666666, 0.0, 0.5], [0.0, -3.183]], [[0.78, 0.12, 1.491, 1.397, 0.2, 0.01, 0.016666666666666666, 0.0, 0.5], [0.186981, 1.32]], [[1.967, 0.183, 0.871, 0.109, 0.1, 0.01, 0.016666666666666666, 0.3, 0.5], [0.0, 1.967]]]]\nfor i, (args, expected) in enumerate(fixtures[N-1]):\n    check(\"case %d\" % i, solve(*args), expected)\nprint(json.dumps({\"observations\": observations, \"passed\": all(x[\"passed\"] for x in observations)}, ensure_ascii=False))\nraise SystemExit(0 if all(x[\"passed\"] for x in observations) else 1)\n"}},"limitations":"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.","method":"Deterministic executable model with adversarial boundary fixtures.","provenance":{"created_by":"Failure Map","dependencies":"Python standard library","family":"w2-physics_integrator_stability-baumgarte-contact-impulse-effective-mass","generated_at":"2026-09-29T14:50:56.642315+00:00","license":"CC0-1.0","python":"3.12.14","seed":1,"split":"open-access"},"relevance":"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.","root_cause":"lam = (target-vn)*w instead of dividing by w.","sha256":"bf058ea7ded0efa5d7527b87accc137ceeecfcd953a170997bece8900a33f0bb","title":"Contact impulse multiplies by the inverse mass sum · case 01","variant":1,"variant_policy":"Five numbered records share a model and may reuse boundary fixtures.","verified":true,"visibility":"public","verification":{"attempt":{"elapsed_ms":40.265,"exit_code":1,"observations":[{"actual":[0.0,-4.177],"check":"case 0","expected":[0.0,-4.177],"passed":true},{"actual":[0.520446,2.328587],"check":"case 1","expected":[0.475921,2.25],"passed":false},{"actual":[5.427586,0.0],"check":"case 2","expected":[5.427586,0.0],"passed":true},{"actual":[3.103277,0.946977],"check":"case 3","expected":[2.723216,0.5901],"passed":false},{"actual":[0.870056,0.816],"check":"case 4","expected":[0.870056,0.816],"passed":true},{"actual":[0.0,1.262],"check":"case 5","expected":[0.0,1.262],"passed":true},{"actual":[1.239316,1.532385],"check":"case 6","expected":[1.074074,1.287],"passed":false},{"actual":[0.0,-1.72],"check":"case 7","expected":[0.0,-1.72],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"case 0\", \"actual\": [0.0, -4.177], \"expected\": [0.0, -4.177], \"passed\": true}, {\"check\": \"case 1\", \"actual\": [0.520446, 2.328587], \"expected\": [0.475921, 2.25], \"passed\": false}, {\"check\": \"case 2\", \"actual\": [5.427586, 0.0], \"expected\": [5.427586, 0.0], \"passed\": true}, {\"check\": \"case 3\", \"actual\": [3.103277, 0.946977], \"expected\": [2.723216, 0.5901], \"passed\": false}, {\"check\": \"case 4\", \"actual\": [0.870056, 0.816], \"expected\": [0.870056, 0.816], \"passed\": true}, {\"check\": \"case 5\", \"actual\": [0.0, 1.262], \"expected\": [0.0, 1.262], \"passed\": true}, {\"check\": \"case 6\", \"actual\": [1.239316, 1.532385], \"expected\": [1.074074, 1.287], \"passed\": false}, {\"check\": \"case 7\", \"actual\": [0.0, -1.72], \"expected\": [0.0, -1.72], \"passed\": true}], \"passed\": false}\n"},"broken":{"elapsed_ms":37.653,"exit_code":1,"observations":[{"actual":[0.0,-4.177],"check":"case 0","expected":[0.0,-4.177],"passed":true},{"actual":[1.4826,4.026789],"check":"case 1","expected":[0.475921,2.25],"passed":false},{"actual":[2.852875,-1.866666],"check":"case 2","expected":[5.427586,0.0],"passed":false},{"actual":[2.401117,0.287649],"check":"case 3","expected":[2.723216,0.5901],"passed":false},{"actual":[0.109032,0.546597],"check":"case 4","expected":[0.870056,0.816],"passed":false},{"actual":[0.0,1.262],"check":"case 5","expected":[0.0,1.262],"passed":true},{"actual":[2.368575,3.209334],"check":"case 6","expected":[1.074074,1.287],"passed":false},{"actual":[0.0,-1.72],"check":"case 7","expected":[0.0,-1.72],"passed":true}],"passed":false,"stderr":"","stdout":"{\"observations\": [{\"check\": \"case 0\", \"actual\": [0.0, -4.177], \"expected\": [0.0, -4.177], \"passed\": true}, {\"check\": \"case 1\", \"actual\": [1.4826, 4.026789], \"expected\": [0.475921, 2.25], \"passed\": false}, {\"check\": \"case 2\", \"actual\": [2.852875, -1.866666], \"expected\": [5.427586, 0.0], \"passed\": false}, {\"check\": \"case 3\", \"actual\": [2.401117, 0.287649], \"expected\": [2.723216, 0.5901], \"passed\": false}, {\"check\": \"case 4\", \"actual\": [0.109032, 0.546597], \"expected\": [0.870056, 0.816], \"passed\": false}, {\"check\": \"case 5\", \"actual\": [0.0, 1.262], \"expected\": [0.0, 1.262], \"passed\": true}, {\"check\": \"case 6\", \"actual\": [2.368575, 3.209334], \"expected\": [1.074074, 1.287], \"passed\": false}, {\"check\": \"case 7\", \"actual\": [0.0, -1.72], \"expected\": [0.0, -1.72], \"passed\": true}], \"passed\": false}\n"}},"member_only":{"stages":["fixed"],"fields":["implementations.fixed","verification.fixed","harness","repair"],"note":"The verified repair, its recorded checks, the repair description, and the scoring harness are available to members."}}