FAILURE MAP
← Case archive

FA-87141 / Physics integrator stability / Open access

Current and previous step lengths are swapped · case 01

Accelerating or decelerating frame rates distort the trajectory in opposite directions.

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

ROOT CAUSE

h and h_prev are read as dts[i-1] and dts[i].

VERIFIED REPAIR

The step being taken is dts[i]; the previous one is dts[i-1].

Unsuccessful approach: Using the first step as the permanent previous step fails after several changes.

Case contract

solve(x0, v0, w2, g, dts): position Verlet with variable steps, acceleration -w2*x+g. First step is Taylor x1=x0+v0*h0+0.5*a(x0)*h0^2; then x_{n+1}=x_n+(x_n-x_{n-1})*(h_n/h_{n-1})+a(x_n)*h_n*(h_n+h_{n-1})/2. Velocity estimate is (x_n-x_{n-1})/h_last. Empty dts returns the initial state. Return [x, v] rounded.

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(x0, v0, w2, g, dts):
    def acc(p):
        return -w2 * p + g
    if not dts:
        return [round(x0, 6), round(v0, 6)]
    prev = x0
    x = x0 + v0 * dts[0] + 0.5 * acc(x0) * dts[0] * dts[0]
    for i in range(1, len(dts)):
        h, hp = dts[i - 1], dts[i]
        nxt = x + (x - prev) * (h / hp) + acc(x) * h * (h + hp) / 2
        prev, x = x, nxt
    v = (x - prev) / dts[-1]
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[0.159, 1.403, 12.469, 0.0, [0.01, 0.02, 0.05]], [0.263816, 1.273396]], [[0.78, -0.691, 5.2, -9.81, [0.01, 0.05, 0.05]], [0.621082, -1.85117]], [[-1.619, -0.338, 11.211, 0.0, [0.03, 0.01, 0.02, 0.01]], [-1.598199, 0.839977]], [[1.835, -1.641, 6.597, 2.0, [0.02, 0.02]], [1.761368, -1.939568]], [[1.699, 1.89, 11.648, 2.0, [0.01, 0.01, 0.01]], [1.747613, 1.439167]], [[-1.409, 0.693, 7.348, -9.81, [0.02, 0.02, 0.05, 0.05, 0.05, 0.01]], [-1.266157, 0.69937]], [[-1.118, 1.653, 18.431, 0.0, [0.03, 0.03]], [-0.982706, 2.547717]], [[1.52, -0.79, 13.208, 2.0, [0.03, 0.03, 0.02, 0.02, 0.05, 0.05]], [1.02811, -3.599677]]], [[[1.821, 1.198, 3.771, 0.0, [0.02, 0.01, 0.05, 0.02, 0.01]], [1.910483, 0.457456]], [[0.644, -0.151, 13.871, -9.81, [0.02, 0.02, 0.01, 0.01, 0.05, 0.02, 0.03]], [0.387894, -2.717601]], [[-1.926, 1.549, 6.213, -9.81, [0.01, 0.03, 0.01, 0.02, 0.02]], [-1.778987, 1.690133]], [[-0.485, 1.456, 18.965, 2.0, [0.01, 0.03, 0.05, 0.05, 0.02, 0.02]], [-0.07504, 2.805631]], [[1.693, 1.184, 10.982, -9.81, [0.02, 0.03, 0.05, 0.05]], [1.550068, -2.368135]], [[0.454, 0.048, 11.925, 0.0, [0.01, 0.01, 0.01]], [0.453003, -0.087359]], [[0.426, -0.985, 9.249, -9.81, [0.02, 0.05, 0.05]], [0.211891, -2.236693]], [[-1.855, 0.692, 12.133, 2.0, [0.02, 0.01, 0.01, 0.03]], [-1.747187, 2.021157]]], [[[1.462, -1.373, 3.135, 0.0, [0.05, 0.02, 0.02, 0.01, 0.02, 0.05, 0.03]], [1.102151, -2.133217]], [[-1.478, -0.428, 14.024, 2.0, [0.01, 0.02, 0.01]], [-1.476913, 0.36867]], [[1.606, 1.967, 9.66, 0.0, [0.05, 0.03, 0.01, 0.02, 0.03, 0.05, 0.01]], [1.674706, -1.223548]], [[-0.31, -1.257, 5.955, 0.0, [0.05, 0.03, 0.05]], [-0.455535, -1.0263]], [[-0.686, 1.111, 17.91, -9.81, [0.05, 0.03, 0.03, 0.03]], [-0.5152, 1.255652]], [[0.106, -1.937, 2.608, 0.0, [0.03, 0.01, 0.03, 0.05, 0.01, 0.05, 0.05, 0.02]], [-0.374085, -1.858207]], [[0.68, 1.896, 12.013, -9.81, [0.03, 0.03, 0.03]], [0.775896, 0.500859]], [[0.152, -1.091, 14.043, 0.0, [0.01, 0.02, 0.01, 0.02, 0.05, 0.01]], [0.009941, -1.229064]]], [[[-1.698, 0.325, 6.546, -9.81, [0.02, 0.02]], [-1.683974, 0.363268]], [[0.382, 0.792, 11.215, 0.0, [0.05, 0.01, 0.02, 0.05, 0.05, 0.03, 0.05, 0.03]], [0.411226, -0.538349]], [[-0.101, 1.196, 2.452, -9.81, [0.03, 0.02, 0.01, 0.03, 0.03, 0.02, 0.03, 0.01, 0.01]], [-0.048386, -0.598008]], [[-0.101, -1.02, 19.226, 2.0, [0.05, 0.01]], [-0.154839, -0.776626]], [[1.286, 1.196, 2.402, 0.0, [0.05, 0.05, 0.02, 0.01, 0.05, 0.05, 0.05, 0.03, 0.05]], [1.499807, 0.049865]], [[1.484, 1.78, 2.899, 2.0, [0.01, 0.02, 0.05, 0.01, 0.03]], [1.679732, 1.511762]], [[1.406, -0.862, 9.145, 0.0, [0.03, 0.01, 0.01, 0.03, 0.01, 0.01]], [1.257218, -2.031082]], [[-0.434, -1.688, 15.899, 0.0, [0.03, 0.05, 0.01, 0.02]], [-0.573341, -0.885589]]], [[[-0.841, -0.714, 0.875, 2.0, [0.05, 0.02, 0.02, 0.01, 0.01, 0.02, 0.02, 0.01]], [-0.919878, -0.283965]], [[-1.17, -1.869, 6.983, 2.0, [0.02, 0.02, 0.01, 0.01, 0.01, 0.03]], [-1.304253, -0.965785]], [[-0.421, -1.461, 6.131, 2.0, [0.02, 0.01, 0.03, 0.05, 0.01, 0.05]], [-0.597191, -0.719646]], [[0.363, 0.71, 3.317, 0.0, [0.01, 0.02]], [0.383751, 0.685568]], [[1.217, -0.953, 5.249, -9.81, [0.02, 0.01]], [1.181138, -1.356195]], [[1.94, 0.689, 18.476, 0.0, [0.05, 0.01, 0.03, 0.01, 0.05, 0.02, 0.03, 0.02, 0.02]], [1.133627, -6.57541]], [[1.097, 0.642, 16.162, 2.0, [0.01, 0.03]], [1.110042, 0.246936]], [[-1.434, -0.348, 10.741, -9.81, [0.03, 0.03, 0.03, 0.01, 0.05, 0.03, 0.03, 0.03, 0.01, 0.01]], [-1.336072, 1.031162]]]]
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[0.180662, 0.021789][0.263816, 1.273396]Failed
case 1[0.726567, -0.803221][0.621082, -1.85117]Failed
case 2[-1.594935, 1.583951][-1.598199, 0.839977]Failed
case 3[1.761368, -1.939568][1.761368, -1.939568]Passed
case 4[1.747613, 1.439167][1.747613, 1.439167]Passed
case 5[-1.324643, 3.648329][-1.266157, 0.69937]Failed
case 6[-0.982706, 2.547717][-0.982706, 2.547717]Passed
case 7[1.136947, -1.636623][1.02811, -3.599677]Failed

SHA-256 / 2675a869d65db3814cbebb33bbc6545fc8025e586ecf3c0081236dedb9acaf7f

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x0, v0, w2, g, dts):
    def acc(p):
        return -w2 * p + g
    if not dts:
        return [round(x0, 6), round(v0, 6)]
    prev = x0
    x = x0 + v0 * dts[0] + 0.5 * acc(x0) * dts[0] * dts[0]
    for i in range(1, len(dts)):
        h, hp = dts[i], dts[0]
        nxt = x + (x - prev) * (h / hp) + acc(x) * h * (h + hp) / 2
        prev, x = x, nxt
    v = (x - prev) / dts[-1]
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[0.159, 1.403, 12.469, 0.0, [0.01, 0.02, 0.05]], [0.263816, 1.273396]], [[0.78, -0.691, 5.2, -9.81, [0.01, 0.05, 0.05]], [0.621082, -1.85117]], [[-1.619, -0.338, 11.211, 0.0, [0.03, 0.01, 0.02, 0.01]], [-1.598199, 0.839977]], [[1.835, -1.641, 6.597, 2.0, [0.02, 0.02]], [1.761368, -1.939568]], [[1.699, 1.89, 11.648, 2.0, [0.01, 0.01, 0.01]], [1.747613, 1.439167]], [[-1.409, 0.693, 7.348, -9.81, [0.02, 0.02, 0.05, 0.05, 0.05, 0.01]], [-1.266157, 0.69937]], [[-1.118, 1.653, 18.431, 0.0, [0.03, 0.03]], [-0.982706, 2.547717]], [[1.52, -0.79, 13.208, 2.0, [0.03, 0.03, 0.02, 0.02, 0.05, 0.05]], [1.02811, -3.599677]]], [[[1.821, 1.198, 3.771, 0.0, [0.02, 0.01, 0.05, 0.02, 0.01]], [1.910483, 0.457456]], [[0.644, -0.151, 13.871, -9.81, [0.02, 0.02, 0.01, 0.01, 0.05, 0.02, 0.03]], [0.387894, -2.717601]], [[-1.926, 1.549, 6.213, -9.81, [0.01, 0.03, 0.01, 0.02, 0.02]], [-1.778987, 1.690133]], [[-0.485, 1.456, 18.965, 2.0, [0.01, 0.03, 0.05, 0.05, 0.02, 0.02]], [-0.07504, 2.805631]], [[1.693, 1.184, 10.982, -9.81, [0.02, 0.03, 0.05, 0.05]], [1.550068, -2.368135]], [[0.454, 0.048, 11.925, 0.0, [0.01, 0.01, 0.01]], [0.453003, -0.087359]], [[0.426, -0.985, 9.249, -9.81, [0.02, 0.05, 0.05]], [0.211891, -2.236693]], [[-1.855, 0.692, 12.133, 2.0, [0.02, 0.01, 0.01, 0.03]], [-1.747187, 2.021157]]], [[[1.462, -1.373, 3.135, 0.0, [0.05, 0.02, 0.02, 0.01, 0.02, 0.05, 0.03]], [1.102151, -2.133217]], [[-1.478, -0.428, 14.024, 2.0, [0.01, 0.02, 0.01]], [-1.476913, 0.36867]], [[1.606, 1.967, 9.66, 0.0, [0.05, 0.03, 0.01, 0.02, 0.03, 0.05, 0.01]], [1.674706, -1.223548]], [[-0.31, -1.257, 5.955, 0.0, [0.05, 0.03, 0.05]], [-0.455535, -1.0263]], [[-0.686, 1.111, 17.91, -9.81, [0.05, 0.03, 0.03, 0.03]], [-0.5152, 1.255652]], [[0.106, -1.937, 2.608, 0.0, [0.03, 0.01, 0.03, 0.05, 0.01, 0.05, 0.05, 0.02]], [-0.374085, -1.858207]], [[0.68, 1.896, 12.013, -9.81, [0.03, 0.03, 0.03]], [0.775896, 0.500859]], [[0.152, -1.091, 14.043, 0.0, [0.01, 0.02, 0.01, 0.02, 0.05, 0.01]], [0.009941, -1.229064]]], [[[-1.698, 0.325, 6.546, -9.81, [0.02, 0.02]], [-1.683974, 0.363268]], [[0.382, 0.792, 11.215, 0.0, [0.05, 0.01, 0.02, 0.05, 0.05, 0.03, 0.05, 0.03]], [0.411226, -0.538349]], [[-0.101, 1.196, 2.452, -9.81, [0.03, 0.02, 0.01, 0.03, 0.03, 0.02, 0.03, 0.01, 0.01]], [-0.048386, -0.598008]], [[-0.101, -1.02, 19.226, 2.0, [0.05, 0.01]], [-0.154839, -0.776626]], [[1.286, 1.196, 2.402, 0.0, [0.05, 0.05, 0.02, 0.01, 0.05, 0.05, 0.05, 0.03, 0.05]], [1.499807, 0.049865]], [[1.484, 1.78, 2.899, 2.0, [0.01, 0.02, 0.05, 0.01, 0.03]], [1.679732, 1.511762]], [[1.406, -0.862, 9.145, 0.0, [0.03, 0.01, 0.01, 0.03, 0.01, 0.01]], [1.257218, -2.031082]], [[-0.434, -1.688, 15.899, 0.0, [0.03, 0.05, 0.01, 0.02]], [-0.573341, -0.885589]]], [[[-0.841, -0.714, 0.875, 2.0, [0.05, 0.02, 0.02, 0.01, 0.01, 0.02, 0.02, 0.01]], [-0.919878, -0.283965]], [[-1.17, -1.869, 6.983, 2.0, [0.02, 0.02, 0.01, 0.01, 0.01, 0.03]], [-1.304253, -0.965785]], [[-0.421, -1.461, 6.131, 2.0, [0.02, 0.01, 0.03, 0.05, 0.01, 0.05]], [-0.597191, -0.719646]], [[0.363, 0.71, 3.317, 0.0, [0.01, 0.02]], [0.383751, 0.685568]], [[1.217, -0.953, 5.249, -9.81, [0.02, 0.01]], [1.181138, -1.356195]], [[1.94, 0.689, 18.476, 0.0, [0.05, 0.01, 0.03, 0.01, 0.05, 0.02, 0.03, 0.02, 0.02]], [1.133627, -6.57541]], [[1.097, 0.642, 16.162, 2.0, [0.01, 0.03]], [1.110042, 0.246936]], [[-1.434, -0.348, 10.741, -9.81, [0.03, 0.03, 0.03, 0.01, 0.05, 0.03, 0.03, 0.03, 0.01, 0.01]], [-1.336072, 1.031162]]]]
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[0.332477, 2.646618][0.263816, 1.273396]Failed
case 1[0.399578, -6.281247][0.621082, -1.85117]Failed
case 2[-1.599653, 0.728789][-1.598199, 0.839977]Failed
case 3[1.761368, -1.939568][1.761368, -1.939568]Passed
case 4[1.747613, 1.439167][1.747613, 1.439167]Passed
case 5[-0.919286, 11.165737][-1.266157, 0.69937]Failed
case 6[-0.982706, 2.547717][-0.982706, 2.547717]Passed
case 7[1.093687, -3.613646][1.02811, -3.599677]Failed

SHA-256 / d47583ccbd1d87f52bce2ea46672771c2e6c1535c8b84493481769caebe52f3b

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
N = 1
observations = []
def solve(x0, v0, w2, g, dts):
    def acc(p):
        return -w2 * p + g
    if not dts:
        return [round(x0, 6), round(v0, 6)]
    prev = x0
    x = x0 + v0 * dts[0] + 0.5 * acc(x0) * dts[0] * dts[0]
    for i in range(1, len(dts)):
        h, hp = dts[i], dts[i - 1]
        nxt = x + (x - prev) * (h / hp) + acc(x) * h * (h + hp) / 2
        prev, x = x, nxt
    v = (x - prev) / dts[-1]
    return [round(x, 6), round(v, 6)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[[[0.159, 1.403, 12.469, 0.0, [0.01, 0.02, 0.05]], [0.263816, 1.273396]], [[0.78, -0.691, 5.2, -9.81, [0.01, 0.05, 0.05]], [0.621082, -1.85117]], [[-1.619, -0.338, 11.211, 0.0, [0.03, 0.01, 0.02, 0.01]], [-1.598199, 0.839977]], [[1.835, -1.641, 6.597, 2.0, [0.02, 0.02]], [1.761368, -1.939568]], [[1.699, 1.89, 11.648, 2.0, [0.01, 0.01, 0.01]], [1.747613, 1.439167]], [[-1.409, 0.693, 7.348, -9.81, [0.02, 0.02, 0.05, 0.05, 0.05, 0.01]], [-1.266157, 0.69937]], [[-1.118, 1.653, 18.431, 0.0, [0.03, 0.03]], [-0.982706, 2.547717]], [[1.52, -0.79, 13.208, 2.0, [0.03, 0.03, 0.02, 0.02, 0.05, 0.05]], [1.02811, -3.599677]]], [[[1.821, 1.198, 3.771, 0.0, [0.02, 0.01, 0.05, 0.02, 0.01]], [1.910483, 0.457456]], [[0.644, -0.151, 13.871, -9.81, [0.02, 0.02, 0.01, 0.01, 0.05, 0.02, 0.03]], [0.387894, -2.717601]], [[-1.926, 1.549, 6.213, -9.81, [0.01, 0.03, 0.01, 0.02, 0.02]], [-1.778987, 1.690133]], [[-0.485, 1.456, 18.965, 2.0, [0.01, 0.03, 0.05, 0.05, 0.02, 0.02]], [-0.07504, 2.805631]], [[1.693, 1.184, 10.982, -9.81, [0.02, 0.03, 0.05, 0.05]], [1.550068, -2.368135]], [[0.454, 0.048, 11.925, 0.0, [0.01, 0.01, 0.01]], [0.453003, -0.087359]], [[0.426, -0.985, 9.249, -9.81, [0.02, 0.05, 0.05]], [0.211891, -2.236693]], [[-1.855, 0.692, 12.133, 2.0, [0.02, 0.01, 0.01, 0.03]], [-1.747187, 2.021157]]], [[[1.462, -1.373, 3.135, 0.0, [0.05, 0.02, 0.02, 0.01, 0.02, 0.05, 0.03]], [1.102151, -2.133217]], [[-1.478, -0.428, 14.024, 2.0, [0.01, 0.02, 0.01]], [-1.476913, 0.36867]], [[1.606, 1.967, 9.66, 0.0, [0.05, 0.03, 0.01, 0.02, 0.03, 0.05, 0.01]], [1.674706, -1.223548]], [[-0.31, -1.257, 5.955, 0.0, [0.05, 0.03, 0.05]], [-0.455535, -1.0263]], [[-0.686, 1.111, 17.91, -9.81, [0.05, 0.03, 0.03, 0.03]], [-0.5152, 1.255652]], [[0.106, -1.937, 2.608, 0.0, [0.03, 0.01, 0.03, 0.05, 0.01, 0.05, 0.05, 0.02]], [-0.374085, -1.858207]], [[0.68, 1.896, 12.013, -9.81, [0.03, 0.03, 0.03]], [0.775896, 0.500859]], [[0.152, -1.091, 14.043, 0.0, [0.01, 0.02, 0.01, 0.02, 0.05, 0.01]], [0.009941, -1.229064]]], [[[-1.698, 0.325, 6.546, -9.81, [0.02, 0.02]], [-1.683974, 0.363268]], [[0.382, 0.792, 11.215, 0.0, [0.05, 0.01, 0.02, 0.05, 0.05, 0.03, 0.05, 0.03]], [0.411226, -0.538349]], [[-0.101, 1.196, 2.452, -9.81, [0.03, 0.02, 0.01, 0.03, 0.03, 0.02, 0.03, 0.01, 0.01]], [-0.048386, -0.598008]], [[-0.101, -1.02, 19.226, 2.0, [0.05, 0.01]], [-0.154839, -0.776626]], [[1.286, 1.196, 2.402, 0.0, [0.05, 0.05, 0.02, 0.01, 0.05, 0.05, 0.05, 0.03, 0.05]], [1.499807, 0.049865]], [[1.484, 1.78, 2.899, 2.0, [0.01, 0.02, 0.05, 0.01, 0.03]], [1.679732, 1.511762]], [[1.406, -0.862, 9.145, 0.0, [0.03, 0.01, 0.01, 0.03, 0.01, 0.01]], [1.257218, -2.031082]], [[-0.434, -1.688, 15.899, 0.0, [0.03, 0.05, 0.01, 0.02]], [-0.573341, -0.885589]]], [[[-0.841, -0.714, 0.875, 2.0, [0.05, 0.02, 0.02, 0.01, 0.01, 0.02, 0.02, 0.01]], [-0.919878, -0.283965]], [[-1.17, -1.869, 6.983, 2.0, [0.02, 0.02, 0.01, 0.01, 0.01, 0.03]], [-1.304253, -0.965785]], [[-0.421, -1.461, 6.131, 2.0, [0.02, 0.01, 0.03, 0.05, 0.01, 0.05]], [-0.597191, -0.719646]], [[0.363, 0.71, 3.317, 0.0, [0.01, 0.02]], [0.383751, 0.685568]], [[1.217, -0.953, 5.249, -9.81, [0.02, 0.01]], [1.181138, -1.356195]], [[1.94, 0.689, 18.476, 0.0, [0.05, 0.01, 0.03, 0.01, 0.05, 0.02, 0.03, 0.02, 0.02]], [1.133627, -6.57541]], [[1.097, 0.642, 16.162, 2.0, [0.01, 0.03]], [1.110042, 0.246936]], [[-1.434, -0.348, 10.741, -9.81, [0.03, 0.03, 0.03, 0.01, 0.05, 0.03, 0.03, 0.03, 0.01, 0.01]], [-1.336072, 1.031162]]]]
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[0.263816, 1.273396][0.263816, 1.273396]Passed
case 1[0.621082, -1.85117][0.621082, -1.85117]Passed
case 2[-1.598199, 0.839977][-1.598199, 0.839977]Passed
case 3[1.761368, -1.939568][1.761368, -1.939568]Passed
case 4[1.747613, 1.439167][1.747613, 1.439167]Passed
case 5[-1.266157, 0.69937][-1.266157, 0.69937]Passed
case 6[-0.982706, 2.547717][-0.982706, 2.547717]Passed
case 7[1.02811, -3.599677][1.02811, -3.599677]Passed

SHA-256 / 7bcd2586e5b1f9442b5f074d07072332dafbef201ea1b471eca080ee68a41776

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:55.996410+00:00.

Case digest / 6774b1cd246932f5cba99593046fb3d53f4fda99298e5807f8c827c988610843